clfwrapper/ClientSrc/CCLFEngineImpl.cpp
changeset 0 c53acadfccc6
child 15 3cebc1a84278
equal deleted inserted replaced
-1:000000000000 0:c53acadfccc6
       
     1 /*
       
     2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include    <MCLFOperationObserver.h>
       
    21 #include    <MCLFSortingStyle.h>
       
    22 #include    <MCLFItem.h>
       
    23 #include    <MCLFChangedItemObserver.h>
       
    24 #include    "CCLFEngineImpl.h"
       
    25 #include    "CCLFDbItemProvider.h"
       
    26 #include    "CCLFItemImpl.h"
       
    27 #include    "CCLFDefaultOperation.h"
       
    28 #include    "CCLFItemListModelImpl.h"
       
    29 #include    "CCLFEventHandler.h"
       
    30 #include    "CCLFDbItemContainer.h"
       
    31 #include    "MGDebugPrint.h"
       
    32 #include    "CCLFQueryAdapter.h"
       
    33 
       
    34 // CONSTANTS
       
    35 const TInt KCLFObserverArrayGranularity( 2 );
       
    36 const TInt KCLFChangedItemIdArrayGranularity( 10 );
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CleanupTempModel
       
    40 // -----------------------------------------------------------------------------
       
    41 //
       
    42 void CCLFEngineImpl::CleanupTempModel( TAny* aObj )
       
    43     {
       
    44     static_cast< CCLFEngineImpl::CCLFTempModel* >( aObj )->ResetModelArray();
       
    45     }
       
    46 
       
    47 // ============================ MEMBER FUNCTIONS ===============================
       
    48 
       
    49 // -----------------------------------------------------------------------------
       
    50 // CCLFEngineImpl::CCLFEngineImpl
       
    51 // -----------------------------------------------------------------------------
       
    52 //
       
    53 CCLFEngineImpl::CCLFEngineImpl()
       
    54     : iCLFServerProxy( NULL ),
       
    55       iMdESession( NULL ),
       
    56       iError( KErrNone ),
       
    57       iUpdateStartEventHandler( NULL ),
       
    58       iUpdateEndEventHandler( NULL ),
       
    59       iChangedItemObserverArray( KCLFObserverArrayGranularity ),
       
    60       iProcessObserverArray( KCLFObserverArrayGranularity ),
       
    61       iDbItemContainer( NULL ),
       
    62       iItemProvider( NULL ),
       
    63       iQueryAdapter( NULL )
       
    64     {
       
    65     }
       
    66 
       
    67 // -----------------------------------------------------------------------------
       
    68 // CCLFEngineImpl::ConstructL
       
    69 // -----------------------------------------------------------------------------
       
    70 //
       
    71 void CCLFEngineImpl::ConstructL()
       
    72     {
       
    73     iMdESession = CMdESession::NewL( *this );
       
    74     if( !iActiveSchedulerWait.IsStarted() )
       
    75         {
       
    76         iActiveSchedulerWait.Start();
       
    77         }
       
    78     User::LeaveIfError( iError );
       
    79     iCLFServerProxy = CCLFServerProxy::NewL( *iMdESession );
       
    80     iQueryAdapter = CCLFQueryAdapter::NewL( *iMdESession );
       
    81     iUpdateStartEventHandler = CCLFEventHandler::NewL( *iCLFServerProxy, *this );
       
    82     iUpdateEndEventHandler = CCLFEventHandler::NewL( *iCLFServerProxy, *this );
       
    83     iDbItemContainer = CCLFDbItemContainer::NewL();
       
    84     iItemProvider = CCLFDbItemProvider::NewL( *iDbItemContainer, *iQueryAdapter, iMdESession );
       
    85     iUpdateEndEventHandler->ObserverUpdateEndEvent();
       
    86     }
       
    87 
       
    88 // -----------------------------------------------------------------------------
       
    89 // CCLFEngineImpl::NewLC
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 CCLFEngineImpl* CCLFEngineImpl::NewLC()
       
    93     {
       
    94     CCLFEngineImpl* self = new( ELeave ) CCLFEngineImpl;
       
    95     CleanupStack::PushL( self );
       
    96     self->ConstructL();
       
    97     return self;
       
    98     }
       
    99 
       
   100 // -----------------------------------------------------------------------------
       
   101 // CCLFEngineImpl::~CCLFEngineImpl
       
   102 // Destructor
       
   103 // -----------------------------------------------------------------------------
       
   104 //
       
   105 CCLFEngineImpl::~CCLFEngineImpl()
       
   106     {
       
   107     delete iItemProvider;
       
   108     delete iUpdateStartEventHandler;
       
   109     delete iUpdateEndEventHandler;
       
   110     delete iDbItemContainer;
       
   111     delete iCLFServerProxy;
       
   112     iChangedItemObserverArray.Close();
       
   113     iProcessObserverArray.Close();
       
   114     delete iQueryAdapter;
       
   115     delete iMdESession;
       
   116     }
       
   117 
       
   118 // -----------------------------------------------------------------------------
       
   119 // CCLFEngineImpl::AddChangedItemObserverL
       
   120 // -----------------------------------------------------------------------------
       
   121 //
       
   122 void CCLFEngineImpl::AddChangedItemObserverL( MCLFChangedItemObserver& aObserver )
       
   123     {
       
   124     iChangedItemObserverArray.AppendL( &aObserver );
       
   125     }
       
   126 
       
   127 // -----------------------------------------------------------------------------
       
   128 // CCLFEngineImpl::RemoveChangedItemObserver
       
   129 // -----------------------------------------------------------------------------
       
   130 //
       
   131 void CCLFEngineImpl::RemoveChangedItemObserver( MCLFChangedItemObserver& aObserver )
       
   132     {
       
   133     const TInt index( iChangedItemObserverArray.Find( &aObserver ) );
       
   134     if ( index >= 0 )
       
   135         {
       
   136         iChangedItemObserverArray.Remove( index );
       
   137         }
       
   138     }
       
   139 
       
   140 // -----------------------------------------------------------------------------
       
   141 // CCLFEngineImpl::AddCLFProcessObserverL
       
   142 // -----------------------------------------------------------------------------
       
   143 //
       
   144 void CCLFEngineImpl::AddCLFProcessObserverL( MCLFProcessObserver& aObserver )
       
   145     {
       
   146     iProcessObserverArray.AppendL( &aObserver );
       
   147     if ( !iUpdateStartEventHandler->IsActive() )
       
   148         {
       
   149         iUpdateStartEventHandler->ObserverUpdateStartEvent();
       
   150         }
       
   151     }
       
   152 
       
   153 // -----------------------------------------------------------------------------
       
   154 // CCLFEngineImpl::RemoveCLFProcessObserver
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 void CCLFEngineImpl::RemoveCLFProcessObserver( MCLFProcessObserver& aObserver )
       
   158     {
       
   159     const TInt index( iProcessObserverArray.Find( &aObserver ) );
       
   160     if ( index >= 0 )
       
   161         {
       
   162         iProcessObserverArray.Remove( index );
       
   163         }
       
   164 
       
   165     StopEventHandling();
       
   166     }
       
   167 
       
   168 // -----------------------------------------------------------------------------
       
   169 // CCLFEngineImpl::UpdateItemsL
       
   170 // -----------------------------------------------------------------------------
       
   171 //
       
   172 void CCLFEngineImpl::UpdateItemsL()
       
   173     {
       
   174     User::LeaveIfError( iCLFServerProxy->UpdateAllItemsL() );
       
   175     }
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // CCLFEngineImpl::UpdateItemsL
       
   179 // -----------------------------------------------------------------------------
       
   180 //
       
   181 void CCLFEngineImpl::UpdateItemsL( const TArray<TCLFItemId>& aItemIDArray )
       
   182     {
       
   183     User::LeaveIfError( iCLFServerProxy->UpdateItemsL( aItemIDArray ) );
       
   184     }
       
   185 
       
   186 // -----------------------------------------------------------------------------
       
   187 // CCLFEngineImpl::UpdateItemsL
       
   188 // -----------------------------------------------------------------------------
       
   189 //
       
   190 void CCLFEngineImpl::UpdateItemsL( TInt aSemanticId, const TDesC8& aOpaqueData )
       
   191     {
       
   192     User::LeaveIfError( iCLFServerProxy->UpdateItemsL( aSemanticId, aOpaqueData ) );
       
   193     }
       
   194 
       
   195 // ---------------------------------------------------------------------------
       
   196 // CCLFEngineImpl::HandleSessionOpened
       
   197 // ---------------------------------------------------------------------------
       
   198 //
       
   199 void CCLFEngineImpl::HandleSessionOpened( CMdESession& /* aSession */, const TInt aError )
       
   200     {
       
   201     MG_DEBUG2( HSO, "[CLF]\t CCLFEngineImpl::HandleSessionOpened %d", aError );
       
   202     iActiveSchedulerWait.AsyncStop();
       
   203 
       
   204     iError = aError;
       
   205     }
       
   206 
       
   207 // ---------------------------------------------------------------------------
       
   208 // CCLFEngineImpl::HandleSessionError
       
   209 // ---------------------------------------------------------------------------
       
   210 //
       
   211 void CCLFEngineImpl::HandleSessionError( CMdESession& /*aSession*/, const TInt aError )
       
   212     {
       
   213     MG_DEBUG2( HSE, "[CLF]\t CCLFEngineImpl::HandleSessionError %d", aError );
       
   214 
       
   215     iError = aError;
       
   216     }
       
   217 
       
   218 // -----------------------------------------------------------------------------
       
   219 // CCLFEngineImpl::CreateListModelLC
       
   220 // -----------------------------------------------------------------------------
       
   221 //
       
   222 MCLFItemListModel* CCLFEngineImpl::CreateListModelLC(
       
   223                                             MCLFOperationObserver& aObserver )
       
   224     {
       
   225 
       
   226     CCLFDbItemProvider* itemProvider = CCLFDbItemProvider::NewL( *iDbItemContainer, *iQueryAdapter, iMdESession );
       
   227     // self takes ownership of itemProvider.
       
   228     CCLFItemListModelImpl* self = CCLFItemListModelImpl::NewLC( itemProvider, aObserver, iChangedItemModel );
       
   229     iChangedItemModel.AddObserverL( self );
       
   230     return self;
       
   231     }
       
   232 
       
   233 // -----------------------------------------------------------------------------
       
   234 // CCLFEngineImpl::CreateListModelLC
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 MCLFItemListModel* CCLFEngineImpl::CreateListModelLC(
       
   238                                             MCLFOperationObserver& aObserver,
       
   239                                             TResourceReader& aReader )
       
   240     {
       
   241     CCLFDbItemProvider* itemProvider = CCLFDbItemProvider::NewL( *iDbItemContainer, *iQueryAdapter, iMdESession );
       
   242     // self takes ownership of itemProvider.
       
   243     CCLFItemListModelImpl* self = CCLFItemListModelImpl::NewLC( itemProvider, aObserver, iChangedItemModel, aReader );
       
   244     iChangedItemModel.AddObserverL( self );
       
   245     return self;
       
   246     }
       
   247 
       
   248 // -----------------------------------------------------------------------------
       
   249 // CCLFEngineImpl::HandleUpdateEndEventL
       
   250 // -----------------------------------------------------------------------------
       
   251 //
       
   252 void CCLFEngineImpl::HandleUpdateEndEventL( const TInt aError )
       
   253     {
       
   254     if ( aError == KErrNone )
       
   255         {
       
   256         // get changed items and add new ones to array
       
   257         RArray< TCLFItemId > changedItemIdArray;
       
   258         CleanupClosePushL( changedItemIdArray );
       
   259         iUpdateEndEventHandler->GetChangedItemsL( changedItemIdArray );
       
   260         const TInt count( changedItemIdArray.Count() );
       
   261         for ( TInt i = 0; i < count; ++i )
       
   262             {
       
   263             const TCLFItemId id( changedItemIdArray[ i ] );
       
   264             const TInt index(
       
   265                     iChangedItemModel.iChangedItemIdArray.Find( id ) );
       
   266             if ( index == KErrNotFound )
       
   267                 {
       
   268                 iChangedItemModel.iChangedItemIdArray.AppendL( id );
       
   269                 }
       
   270             }
       
   271         CleanupStack::PopAndDestroy( &changedItemIdArray );
       
   272 
       
   273         if ( iChangedItemModel.iChangedItemIdArray.Count() )
       
   274             {
       
   275             iDbItemContainer->SetDeprecatedItems(
       
   276                                     iChangedItemModel.iChangedItemIdArray );
       
   277 
       
   278             iItemProvider->PrepareItemsL(
       
   279                                 iChangedItemModel.iChangedItemIdArray.Array(),
       
   280                                 *this );
       
   281             }
       
   282         else
       
   283             {
       
   284             // no changed items -> just notify process observers
       
   285             NotifyProcessObserversL( ECLFUpdateStop );
       
   286             }
       
   287         }
       
   288     else
       
   289         {
       
   290         const TInt count( iChangedItemObserverArray.Count() );
       
   291         for ( TInt i = 0 ; i < count ; ++i )
       
   292             {
       
   293             iChangedItemObserverArray[i]->HandleError( aError );
       
   294             }
       
   295         }
       
   296     }
       
   297 
       
   298 // -----------------------------------------------------------------------------
       
   299 // CCLFEngineImpl::OperationCompleteL
       
   300 // -----------------------------------------------------------------------------
       
   301 //
       
   302 void CCLFEngineImpl::OperationCompleteL( const TInt aError )
       
   303     {
       
   304     // make sure that changed item model is reset
       
   305     // array must be reset when changed items are handled (also in leave case)
       
   306     CleanupStack::PushL( TCleanupItem( CleanupTempModel,
       
   307                                        &iChangedItemModel) );
       
   308 
       
   309     if ( aError )
       
   310         {
       
   311         const TInt count( iChangedItemObserverArray.Count() );
       
   312         for( TInt i = 0 ; i < count ; ++i )
       
   313             {
       
   314             iChangedItemObserverArray[i]->HandleError( aError );
       
   315             }
       
   316         }
       
   317     else
       
   318         {
       
   319         // put items to container
       
   320         User::LeaveIfError( iItemProvider->GetItems(
       
   321                                     iChangedItemModel.iItemArray ) );
       
   322 
       
   323         // notify process observers
       
   324         NotifyProcessObserversL( ECLFUpdateStop );
       
   325 
       
   326         // notify changed item observers
       
   327         if ( iChangedItemModel.iChangedItemIdArray.Count() > 0 )
       
   328             {
       
   329             const TInt count( iChangedItemObserverArray.Count() );
       
   330             for( TInt i = 0 ; i < count ; ++i )
       
   331                 {
       
   332                 iChangedItemObserverArray[i]->HandleItemChangeL(
       
   333                             iChangedItemModel.iChangedItemIdArray.Array() );
       
   334                 }
       
   335 
       
   336             // notify models
       
   337             iChangedItemModel.NotifyObserverL();
       
   338             }
       
   339         }
       
   340     CleanupStack::PopAndDestroy(); // TCleanupItem
       
   341     }
       
   342 
       
   343 // -----------------------------------------------------------------------------
       
   344 // CCLFEngineImpl::HandleUpdateStartEventL
       
   345 // -----------------------------------------------------------------------------
       
   346 //
       
   347 void CCLFEngineImpl::HandleUpdateStartEventL( const TInt aError )
       
   348     {
       
   349     if ( aError == KErrNone )
       
   350         {
       
   351         NotifyProcessObserversL( ECLFUpdateStart );
       
   352         }
       
   353     }
       
   354 
       
   355 // -----------------------------------------------------------------------------
       
   356 // CCLFEngineImpl::NotifyProcessObserversL
       
   357 // -----------------------------------------------------------------------------
       
   358 //
       
   359 void CCLFEngineImpl::NotifyProcessObserversL( TCLFProcessEvent aEvent )
       
   360     {
       
   361     const TInt count( iProcessObserverArray.Count() );
       
   362     for ( TInt i = 0 ; i < count ; ++i )
       
   363         {
       
   364         iProcessObserverArray[i]->HandleCLFProcessEventL( aEvent );
       
   365         }
       
   366     }
       
   367 
       
   368 // -----------------------------------------------------------------------------
       
   369 // CCLFEngineImpl::StopEventHandling
       
   370 // -----------------------------------------------------------------------------
       
   371 //
       
   372 void CCLFEngineImpl::StopEventHandling()
       
   373     {
       
   374     if ( iProcessObserverArray.Count() == 0 )
       
   375         {
       
   376         // stop "start observing"
       
   377         iUpdateStartEventHandler->Cancel();
       
   378         }
       
   379     }
       
   380 
       
   381 // -----------------------------------------------------------------------------
       
   382 // CCLFEngineImpl::CCLFTempModel::IsItemsForModel
       
   383 // -----------------------------------------------------------------------------
       
   384 //
       
   385 TBool CCLFEngineImpl::CCLFTempModel::IsItemsForModel(
       
   386                                         const MDesCArray& aMimeTypes,
       
   387                                         const TArray<TInt>& aMediaTypes,
       
   388                                         const TArray<TUint>& aModelItemIds )
       
   389     {
       
   390     // first from item IDs
       
   391     TInt count( aModelItemIds.Count() );
       
   392     for ( TInt i = 0 ; i < count ; ++i )
       
   393         {
       
   394         const TInt index( iChangedItemIdArray.FindInOrder( aModelItemIds[ i ] ) );
       
   395         if( index >= 0 )
       
   396             {
       
   397             return ETrue;
       
   398             }
       
   399         }
       
   400 
       
   401     // find second from media types (faster)
       
   402     count = aMediaTypes.Count();
       
   403     for ( TInt i = 0 ; i < count ; ++i )
       
   404         {
       
   405         const TInt index( iMediaTypeArray.FindInOrder( aMediaTypes[ i ] ) );
       
   406         if ( index >= 0 )
       
   407             {
       
   408             return ETrue;
       
   409             }
       
   410         }
       
   411 
       
   412     // and mimetypes, final from mimetypes, 
       
   413     // because descriptor comparation is slow
       
   414     count = aMimeTypes.MdcaCount();
       
   415     const TInt mCount( iMimeTypeArray.MdcaCount() );
       
   416     for ( TInt i = 0 ; i < count ; ++i )
       
   417         {
       
   418         // match model mimetypes to changed item(s) mimetypes
       
   419         const TDesC& modelMimeType = aMimeTypes.MdcaPoint( i );
       
   420         for ( TInt j = 0 ; j < mCount ; ++j )
       
   421             {
       
   422             const TDesC& changedItemMimeType = iMimeTypeArray.MdcaPoint( j );
       
   423             const TInt match( changedItemMimeType.Match( modelMimeType ) );
       
   424             if ( match != KErrNotFound )
       
   425                 {
       
   426                 return ETrue;
       
   427                 }
       
   428             }
       
   429         }
       
   430 
       
   431     return EFalse;
       
   432     }
       
   433 
       
   434 // -----------------------------------------------------------------------------
       
   435 // CCLFEngineImpl::CCLFTempModel::CCLFTempModel
       
   436 // -----------------------------------------------------------------------------
       
   437 //
       
   438 CCLFEngineImpl::CCLFTempModel::CCLFTempModel()
       
   439     : iItemArray( KCLFChangedItemIdArrayGranularity ),
       
   440       iChangedItemIdArray( KCLFChangedItemIdArrayGranularity ),
       
   441       iChangedItemProviderObserverArray( KCLFChangedItemIdArrayGranularity ),
       
   442       iMimeTypeArray( KCLFChangedItemIdArrayGranularity ),
       
   443       iMediaTypeArray( KCLFChangedItemIdArrayGranularity )
       
   444     {
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 // CCLFEngineImpl::CCLFTempModel::~CCLFTempModel
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 CCLFEngineImpl::CCLFTempModel::~CCLFTempModel()
       
   452     {
       
   453     ResetModelArray();
       
   454     iChangedItemProviderObserverArray.Close();
       
   455     }
       
   456 
       
   457 // -----------------------------------------------------------------------------
       
   458 // CCLFEngineImpl::CCLFTempModel::AddObserverL
       
   459 // -----------------------------------------------------------------------------
       
   460 //
       
   461 void CCLFEngineImpl::CCLFTempModel::AddObserverL(
       
   462                                 MCLFChangedItemProviderObserver* aObserver )
       
   463     {
       
   464     iChangedItemProviderObserverArray.AppendL( aObserver );
       
   465     }
       
   466 
       
   467 // -----------------------------------------------------------------------------
       
   468 // CCLFEngineImpl::CCLFTempModel::ResetModelArray
       
   469 // -----------------------------------------------------------------------------
       
   470 //
       
   471 void CCLFEngineImpl::CCLFTempModel::ResetModelArray()
       
   472     {
       
   473     iItemArray.ResetAndDestroy();
       
   474     iMimeTypeArray.Reset();
       
   475     iMediaTypeArray.Reset();
       
   476     iChangedItemIdArray.Reset();
       
   477     }
       
   478 
       
   479 // -----------------------------------------------------------------------------
       
   480 // CCLFEngineImpl::CCLFTempModel::NotifyObserverL
       
   481 // -----------------------------------------------------------------------------
       
   482 //
       
   483 void CCLFEngineImpl::CCLFTempModel::NotifyObserverL()
       
   484     {
       
   485     PrepareModelL();
       
   486 
       
   487     const TInt providerObserverCount(
       
   488                                     iChangedItemProviderObserverArray.Count() );
       
   489     for ( TInt i = 0 ; i < providerObserverCount ; ++i )
       
   490         {
       
   491         iChangedItemProviderObserverArray[i]->NewChangedItemsL();
       
   492         }
       
   493     }
       
   494 
       
   495 // -----------------------------------------------------------------------------
       
   496 // CCLFEngineImpl::CCLFTempModel::PrepareModelL
       
   497 // -----------------------------------------------------------------------------
       
   498 //
       
   499 void CCLFEngineImpl::CCLFTempModel::PrepareModelL()
       
   500     {
       
   501     // sort array for faster find
       
   502     iChangedItemIdArray.Sort();
       
   503 
       
   504     // get mimetypes and media types from items
       
   505     const TInt modelCount( iItemArray.Count() );
       
   506     for ( TInt i = 0 ; i < modelCount ; ++i )
       
   507         {
       
   508         MCLFItem* item = iItemArray[ i ];
       
   509 
       
   510         TInt32 mediaType( 0 );
       
   511         TInt error( item->GetField( ECLFFieldIdMediaType, mediaType ) );
       
   512         if ( error == KErrNone &&
       
   513             iMediaTypeArray.FindInOrder( mediaType ) == KErrNotFound )
       
   514             {
       
   515             User::LeaveIfError( iMediaTypeArray.InsertInOrder( mediaType ) );
       
   516             }
       
   517         TPtrC mimeType;
       
   518         error = item->GetField( ECLFFieldIdMimeType, mimeType );
       
   519         TInt pos( 0 );
       
   520         if ( error == KErrNone &&
       
   521             iMimeTypeArray.FindIsq( mimeType, pos ) != 0 ) // not found
       
   522             {
       
   523             iMimeTypeArray.InsertIsqL( mimeType );
       
   524             }
       
   525         }
       
   526     }
       
   527 
       
   528 // -----------------------------------------------------------------------------
       
   529 // CCLFEngineImpl::CCLFTempModel::ChangedItemProviderRemoveObserver
       
   530 // -----------------------------------------------------------------------------
       
   531 //
       
   532 void CCLFEngineImpl::CCLFTempModel::RemoveChangedItemProviderObserver(
       
   533                                 MCLFChangedItemProviderObserver* aObserver )
       
   534     {
       
   535     const TInt index( iChangedItemProviderObserverArray.Find( aObserver ) );
       
   536     if ( index >= 0 )
       
   537         {
       
   538         iChangedItemProviderObserverArray.Remove( index );
       
   539         }
       
   540     }
       
   541 
       
   542 //  End of File