commsfwtools/preparedefaultcommsdatabase/src/MetaDatabaseVisitorRecordLink.cpp
changeset 0 dfb7c4ff071f
child 12 8b5d60ce1e94
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // File  MDBVisitorRecordLink.cpp
       
     2 //
       
     3 
       
     4 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     5 // All rights reserved.
       
     6 // This component and the accompanying materials are made available
       
     7 // under the terms of "Eclipse Public License v1.0"
       
     8 // which accompanies this distribution, and is available
       
     9 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    10 //
       
    11 // Initial Contributors:
       
    12 // Nokia Corporation - initial contribution.
       
    13 //
       
    14 // Contributors:
       
    15 //
       
    16 // Description:
       
    17 // Visitor that interacts with the central repository for CMDBRecordLink
       
    18 // A record link field in a record is treated as a field of type TMDBElementId
       
    19 // and is therefore handled by the standard visitor class
       
    20 // This class is for explicit MMetaDatabase calls on the CMDBRecordLink element itself
       
    21 // 
       
    22 //
       
    23 
       
    24 /**
       
    25  @file
       
    26  @internalComponent
       
    27 */
       
    28  
       
    29 
       
    30 #include "CommsDatInternalDefs.h"
       
    31 #include <commsdattypesv1_1.h>
       
    32 #include <comms-infras/commsdatschema.h>
       
    33 
       
    34 
       
    35 using namespace CommsDat;
       
    36 using namespace CommsDatInternal;
       
    37 using namespace Meta;
       
    38 
       
    39 
       
    40 
       
    41 CommsDat::TMDBRecordLinkVisitor::TMDBRecordLinkVisitor(CMDBElement** aData)
       
    42  /* note that data in base class will be set on SetOwner*/
       
    43 : CommsDat::TMDBVisitor<TInt>(NULL), iLinkedRecord(aData)
       
    44 /**
       
    45  * Constructor
       
    46  */
       
    47     {
       
    48     }
       
    49 
       
    50 
       
    51 CommsDat::TMDBRecordLinkVisitor* CommsDat::TMDBRecordLinkVisitor::NewL(const TAny* aMem, const TAny* aData)
       
    52 /**
       
    53  * Instantiates a RecordSet Visitor of a particular type.
       
    54  * Used for attribute registration (in the data v-table).
       
    55  */
       
    56     {
       
    57     return static_cast<CommsDat::TMDBRecordLinkVisitor*>( ::new ((TUint8*)aMem) TMDBRecordLinkVisitor( (CMDBElement**)aData ) );
       
    58     }
       
    59 
       
    60 
       
    61 TInt CommsDat::TMDBRecordLinkVisitor::Changed() const
       
    62 /*
       
    63 when this is not an int
       
    64  composite class always returns changed so iterator will look for changed members.
       
    65 */
       
    66     {
       
    67     if (iOwner && (iOwner->Type() != ELink ))
       
    68         {
       
    69         return TMDBVisitor<TInt>::Changed();
       
    70         }
       
    71 
       
    72     return 1;
       
    73     }
       
    74 
       
    75 
       
    76 
       
    77 void CommsDat::TMDBRecordLinkVisitor::SetOwner(CMDBElement* aOwner)
       
    78 /*
       
    79 Set the owner of this element as is needed for callback.
       
    80 Also set a pointer to the value in the owner for convenience
       
    81 @internalComponent
       
    82 */  
       
    83 	{ 
       
    84     TMDBVisitorBase::SetOwner(aOwner);
       
    85 
       
    86     // now set iTarget to have easy access to the link field value
       
    87     if (iTarget == NULL)
       
    88         {
       
    89         iTarget = reinterpret_cast<SMDBMetaElement<TInt>*>(aOwner->Data());
       
    90         }
       
    91     }
       
    92 
       
    93 
       
    94 void CommsDat::TMDBRecordLinkVisitor::CheckLinkValueL(TMDBElementId aLinkedElementId)
       
    95 /*
       
    96 utility to check the value of this field specifies <Table><Record>.  
       
    97 Nothing less and nothing more.  
       
    98 Caller compliance and validation should already have got us to this point.
       
    99 
       
   100 @internalComponent
       
   101 */     
       
   102     {
       
   103     if ( (aLinkedElementId & KCDMaskShowRecordType) == 0  ||
       
   104          (aLinkedElementId & KCDMaskShowRecordId) == 0 ||
       
   105          (aLinkedElementId & ~KCDMaskShowRecordTypeAndId) != 0 )
       
   106         {
       
   107         __FLOG_STATIC1(KLogComponent, KCDErrLog, 
       
   108             _L("TMDBRecordLinkVisitor::CheckLinkedValueL() - link Value of <%08x> does not specify a table and record id and is not valid."), aLinkedElementId);
       
   109         
       
   110         User::Leave(KErrArgument);   
       
   111         }        
       
   112     }
       
   113 
       
   114 
       
   115 void CommsDat::TMDBRecordLinkVisitor::CheckLinkedRecordL(TMDBElementId aLinkedElementId)
       
   116 /*
       
   117 utility to check the linked record 
       
   118 
       
   119 @internalcomponent
       
   120 */
       
   121     {
       
   122     if (iLinkedRecord != NULL  &&  *iLinkedRecord != NULL)
       
   123         {
       
   124         // just check the record is the right type
       
   125         if ( (aLinkedElementId & KCDMaskShowRecordTypeAndId) != 
       
   126              ((*iLinkedRecord)->ElementId() & KCDMaskShowRecordTypeAndId) )
       
   127             {
       
   128             __FLOG_STATIC2(KLogComponent, KCDErrLog, 
       
   129                 _L("TMDBRecordLinkVisitor::CheckLinkedRecordL() - TypeId given in field value <%08x> and type of linked record <%08x> do not match. Link not usable."), (aLinkedElementId & KCDMaskShowRecordType), (*iLinkedRecord)->TypeId() & KCDMaskShowRecordType);
       
   130 
       
   131             User::Leave(KErrArgument);   
       
   132             }
       
   133         }
       
   134     }
       
   135 
       
   136 void CommsDat::TMDBRecordLinkVisitor::MaintainBCForLegacyLinks()
       
   137 // yes this is a hack but need something to give clients the value 
       
   138 // they expect in order to maintain bc
       
   139     {
       
   140     if (iTarget->iValue > KCDMaxRecords)
       
   141         {
       
   142         if( ( (iTarget->iElementId & KCDMaskShowRecordType ) < KCDTIdAccessPointRecord    &&
       
   143               (iTarget->iElementId & KCDMaskShowRecordType ) != KCDTIdWLANServiceExtRecord  ) )//||
       
   144         //    (iTarget->iElementId & KCDMaskShowType ) == KCDTIdSelectionPolicy                 ||
       
   145         //    (iTarget->iElementId & KCDMaskShowRecordType ) == KCDTIdApPrioritySelectionPolicyRecord  )
       
   146             {
       
   147             iTarget->iValue = ((iTarget->iValue & KCDMaskShowRecordId) >> 8);
       
   148             }
       
   149         }
       
   150     }
       
   151 
       
   152 
       
   153 void CommsDat::TMDBRecordLinkVisitor::CreateLinkedRecordL(CMDBSession& aSession, TMDBElementId aLinkedElementId)
       
   154 /*
       
   155 utility to create the linked record 
       
   156 
       
   157 @internalcomponent
       
   158 */
       
   159     {
       
   160     if (iLinkedRecord != NULL && *iLinkedRecord == NULL )
       
   161         {
       
   162 
       
   163         if ((aLinkedElementId & KCDMaskShowRecordType) == 0)
       
   164             {
       
   165             aLinkedElementId = CommsDatSchema::GetLinkIdL(aSession, iTarget->iElementId, iTarget->iValue, (*iLinkedRecord)? (*iLinkedRecord)->ElementId(): 0/*, iOwner*/);
       
   166             }
       
   167         // Create a new record of the appropriate type
       
   168 	    // trap is here to maintain behaviour compatibility
       
   169 	    TRAPD(err, *iLinkedRecord = CCDRecordBase::RecordFactoryL(aLinkedElementId & KCDMaskShowRecordType);)
       
   170 	    
       
   171         if(err != KErrNone)
       
   172 	      	{
       
   173 			__FLOG_STATIC2(KLogComponent, KCDErrLog, _L("TMDBRecordLinkVisitor::MaybeCreateLinkedRecordL() Link Record creation for id <%08x> failed with err <%d>."), aLinkedElementId, err);
       
   174            
       
   175             User::Leave(err);    
       
   176             }
       
   177 
       
   178         (*iLinkedRecord)->SetElementId(aLinkedElementId | KCDMaskShowFieldType);
       
   179         }
       
   180     }
       
   181 
       
   182 TInt CommsDat::TMDBRecordLinkVisitor::GetL(CMDBSessionImpl* aSession) 
       
   183 /*
       
   184 Assumes fully resolved element Id but still needs mask for reserved bits
       
   185 
       
   186 @internalComponent
       
   187 */
       
   188     {
       
   189     TInt err = TMDBVisitor<TInt>::GetL(aSession);
       
   190    
       
   191     if (err == KErrNone && iOwner->Type() != ELink)
       
   192         {
       
   193         MaintainBCForLegacyLinks();
       
   194         }
       
   195         
       
   196 	return err;
       
   197     }
       
   198 
       
   199 TInt CommsDat::TMDBRecordLinkVisitor::LoadL(CMDBSessionImpl* aSession, TMDBElementId aRecordId, TMDBAttributeFlags aAttributeFlags) 
       
   200 /*
       
   201 Assumes type and record id set by caller
       
   202 
       
   203 @internalComponent
       
   204 */
       
   205     {
       
   206     // First load the link id which is the value in this field 
       
   207     TInt err = TMDBVisitor<TInt>::LoadL(aSession, (*iElementId & ~KCDMaskShowRecordId) | (aRecordId & KCDMaskShowRecordId), aAttributeFlags);
       
   208     
       
   209     if (iOwner->Type() == ELink &&
       
   210         err == KErrNone )
       
   211         {
       
   212         if (iLinkedRecord != NULL && *iLinkedRecord != NULL)
       
   213             {
       
   214             CheckLinkedRecordL(iTarget->iValue);
       
   215 
       
   216             (*iLinkedRecord)->SetRecordId(iTarget->iValue);
       
   217 
       
   218             (*iLinkedRecord)->LoadL(aSession->iOwner);
       
   219             }
       
   220         else 
       
   221             {
       
   222             CreateLinkedRecordL(aSession->iOwner, iTarget->iValue);
       
   223             if(*iLinkedRecord != NULL)
       
   224             	{
       
   225 	            TRAPD(err, (*iLinkedRecord)->LoadL(aSession->iOwner));
       
   226 	            
       
   227 	            if (err != KErrNone)
       
   228 	                {
       
   229 	                delete *iLinkedRecord;
       
   230 	                *iLinkedRecord = NULL;
       
   231 	                }
       
   232             	}
       
   233             }
       
   234         }
       
   235 
       
   236     MaintainBCForLegacyLinks();
       
   237     
       
   238     return err;
       
   239     }
       
   240 
       
   241 
       
   242 TInt CommsDat::TMDBRecordLinkVisitor::LoadL(CMDBSessionImpl* aSession, TMDBElementId aElementId, TMDBAttributeFlags aAttributeFlags, RArray<TUint32>& /*aIds*/)    
       
   243 /* 
       
   244 // KErrNoMatch
       
   245 // KErrNoAuthorisation
       
   246 
       
   247 @internalComponent
       
   248 */
       
   249     {      
       
   250     return LoadL(aSession, aElementId, aAttributeFlags);
       
   251     }   
       
   252  
       
   253 
       
   254 
       
   255 TInt CommsDat::TMDBRecordLinkVisitor::FindL(CMDBSessionImpl* aSession, RArray<TUint32>& aIds)
       
   256 /*
       
   257 Find fields checking whether the value matches the instantiated one if set.  The value must first be translated into
       
   258 the <table><record> format so that a match can be found.
       
   259 // KErrNoMatch
       
   260 // KErrNoAuthorisation
       
   261  * 
       
   262 @internalComponent
       
   263 */
       
   264     {   
       
   265     TInt err(KErrNone);
       
   266 
       
   267     if ( iOwner->Type() == ELink &&
       
   268          iLinkedRecord  != NULL  && 
       
   269          *iLinkedRecord != NULL)
       
   270         {
       
   271         // Find the linked record
       
   272 
       
   273         TBool found = (*iLinkedRecord)->FindL(aSession->iOwner);
       
   274     
       
   275         // set the value to match the record if it wasn't specifically changed
       
   276         if ( found )
       
   277             {
       
   278             if (!TMDBVisitor<TInt>::Changed() )
       
   279                 {
       
   280                 iTarget->iValue = (*iLinkedRecord)->ElementId() & KCDMaskShowRecordTypeAndId;
       
   281                 Change();
       
   282                 }
       
   283             else
       
   284                 {
       
   285                 CheckLinkedRecordL(iTarget->iValue);
       
   286                 }
       
   287             }
       
   288         else
       
   289             {
       
   290             err = KErrNotFound;
       
   291             }
       
   292         }
       
   293       
       
   294     // Then find the linking field
       
   295     if ( err == KErrNone  &&  TMDBVisitor<TInt>::Changed() )
       
   296         { 
       
   297      
       
   298         // first validate the linking field - have to trap in case is not valid
       
   299         TInt temp(0);
       
   300             
       
   301  
       
   302             {
       
   303             TRAPD(trapErr, temp = CommsDatSchema::GetLinkIdL(aSession->iOwner, iTarget->iElementId, 
       
   304             								iTarget->iValue, (iLinkedRecord? (*iLinkedRecord)->ElementId(): 0), 
       
   305             								iOwner ); );
       
   306     
       
   307             if (trapErr != KErrNone)
       
   308                 {
       
   309                 if (trapErr == KErrArgument)
       
   310                     {
       
   311                     return KErrNotFound;
       
   312                     }
       
   313                 else
       
   314                     {
       
   315                     // some other error has occurred
       
   316                     User::Leave(trapErr);
       
   317                     }
       
   318                 }
       
   319             }
       
   320 
       
   321        // Now look for the field with the value of temp    
       
   322 
       
   323         TInt mask = KCDMaskShowType;
       
   324 
       
   325         // First look for the given value
       
   326 	    err = aSession->StorageL()->FindEqL(ElementId() & ~aSession->GetReadAttributeMask(), mask, temp, aIds);
       
   327 
       
   328         if ( aIds.Count() <= 0 )
       
   329             {
       
   330             if (err == KErrNotFound)
       
   331                 {
       
   332                 // then try just looking for the value of the recordId on its own
       
   333                 err = aSession->StorageL()->FindEqL(ElementId() & ~aSession->GetReadAttributeMask(), mask, (temp & KCDMaskShowInstance), aIds);
       
   334                 }
       
   335 #ifdef __DEBUG // because only doing this for logging
       
   336             if ( err != KErrNone  ||  aIds.Count() <= 0 )
       
   337                 {
       
   338                 if (err == KErrNone || err == KErrNotFound)
       
   339                     {
       
   340                     __FLOG_STATIC3(KLogComponent, KCDInfoLog, _L("TMDBRecordLinkVisitor::FindL() storage server FindEqL() did not find field <%08x>, value <%08x>"), ElementId(), iTarget->iValue, err);
       
   341                     }
       
   342                 else
       
   343                     {
       
   344                     __FLOG_STATIC3(KLogComponent, KCDErrLog, _L("TMDBRecordLinkVisitor::FindL() storage server FindEqL() for field <%08x>, value <%08x>, returned unexpected err <%d>"), ElementId(), iTarget->iValue, err);
       
   345                     }
       
   346                 }
       
   347 #endif             
       
   348             }
       
   349         }
       
   350 
       
   351     return err;
       
   352     }
       
   353  
       
   354  
       
   355  
       
   356 TInt CommsDat::TMDBRecordLinkVisitor::RefreshL(CMDBSessionImpl* aSession)
       
   357 /*
       
   358 Refresh existing data where it has not been changed
       
   359 // KErrNoMatch
       
   360 // KErrNoAuthorisation     
       
   361 
       
   362 @internalComponent
       
   363 */
       
   364     {         
       
   365     if (! aSession || ! aSession->StorageL())
       
   366         User::Leave(KErrNotReady);
       
   367 
       
   368     TInt err(KErrGeneral); 
       
   369     
       
   370     //First refresh the field
       
   371     if ( TMDBVisitor<TInt>::Changed() )
       
   372         {
       
   373         err = TMDBVisitor<TInt>::RefreshL(aSession);
       
   374         }
       
   375 
       
   376     if ( iOwner->Type() == ELink &&
       
   377          err == KErrNone  &&
       
   378          iLinkedRecord != NULL  && 
       
   379          *iLinkedRecord != NULL )
       
   380         {          
       
   381         // Now refresh the linked record too
       
   382 
       
   383         CheckLinkedRecordL(iTarget->iValue);
       
   384 
       
   385         (*iLinkedRecord)->SetRecordId(iTarget->iValue);
       
   386 
       
   387         (*iLinkedRecord)->RefreshL(aSession->iOwner);
       
   388         }
       
   389 
       
   390     if (! TMDBVisitor<TInt>::Changed())
       
   391         {
       
   392         MaintainBCForLegacyLinks();
       
   393         }
       
   394 
       
   395     return err;
       
   396     }
       
   397 
       
   398 
       
   399 void CommsDat::TMDBRecordLinkVisitor::SetLinkValueL(CMDBSession& aSession)
       
   400 // always store the fully qualified link id (table and Record)
       
   401     {
       
   402  //   if ( (iTarget->iValue & KLinkableTag) != NULL)
       
   403        // { // change the link value to table/record
       
   404         iTarget->iValue = CommsDatSchema::GetLinkIdL(aSession, iTarget->iElementId, iTarget->iValue, 0/*, iOwner*/);
       
   405    //     }
       
   406    // else
       
   407 //        { // just validate the link
       
   408     //    TInt temp = CommsDatSchema::GetLinkIdL(aSession, iTarget->iElementId, iTarget->iValue, NULL, iOwner);
       
   409      //   }
       
   410     }
       
   411 
       
   412 
       
   413 TInt CommsDat::TMDBRecordLinkVisitor::StoreL(CMDBSessionImpl* aSession, TMDBElementId aRecordId, TMDBAttributeFlags aAttributeFlags)
       
   414 /*
       
   415 Create a new linked field.
       
   416 If the linked record is also attached then create it as well if necessary.
       
   417 if the linked record is present it is assumed the client has changed it appropriately
       
   418 // KErrNoAuthorisation
       
   419 // KErrAlreadyExists
       
   420 @internalComponent
       
   421 */
       
   422     {         
       
   423     if (! iTarget || ! iElementId || ! aSession->StorageL())
       
   424         {
       
   425         User::Leave(KErrNotReady);
       
   426         }
       
   427 
       
   428     if ( iTarget->iValue == 0)
       
   429         {
       
   430         return KErrNone; // pointless to store an empty link  
       
   431         }
       
   432 
       
   433     // First find the tableid of the linked field...
       
   434 
       
   435     // Translate this link field into a storable element id <Table><Record> if enough information is present
       
   436     SetLinkValueL(aSession->iOwner);
       
   437 
       
   438  //   __FLOG_STATIC2(KLogComponent, KCDInfoLog, _L("TMDBRecordLinkVisitor StoreL() storing link value <%08x> in field <%08x>"), iTarget->iValue,  ElementId());
       
   439   //  TUInt32 storeVal = iTarget->iValue > KCDMaxRecords ? (iTarget->iValue >> 8 ): iTarget->iValue)
       
   440         
       
   441     *iElementId = (*iElementId & ~KCDMaskShowRecordId) | (aRecordId & KCDMaskShowRecordId) | aAttributeFlags;            
       
   442     TInt err = aSession->StorageL()->Create( ElementId() & KCDMaskHideRes, iTarget->iValue);
       
   443    
       
   444     if (err != KErrNone)
       
   445         {
       
   446         __FLOG_STATIC2(KLogComponent, KCDErrLog, _L("TMDBRecordLinkVisitor StoreL() storage server StoreL failed with err <%d> when storing field <%08x>"), err,  ElementId());
       
   447         }
       
   448     else if ( iOwner->Type() == ELink  &&
       
   449               iLinkedRecord != NULL  &&  *iLinkedRecord != NULL )
       
   450         {
       
   451         // Now store the linked record too
       
   452 
       
   453         // Check that the link value is consistent with the linked record
       
   454         CheckLinkedRecordL(iTarget->iValue);
       
   455         
       
   456         (*iLinkedRecord)->SetRecordId(iTarget->iValue);
       
   457 
       
   458         // ensure the record id is set and then call StoreL on the linked record
       
   459         (*iLinkedRecord)->StoreL(aSession->iOwner); 
       
   460         }
       
   461 
       
   462     MaintainBCForLegacyLinks();
       
   463     
       
   464 	return err;
       
   465     }
       
   466     
       
   467  
       
   468 TInt CommsDat::TMDBRecordLinkVisitor::ModifyL(CMDBSessionImpl* aSession, TMDBAttributeFlags aAttributeFlags)
       
   469 /*
       
   470 Modify field in the store
       
   471 Assumes that client has correctly changed the linkedRecord if changed the link value
       
   472 // KErrNoAuthorisation
       
   473 // KErrNoMatch
       
   474 @internalComponent
       
   475 */
       
   476     {         
       
   477     if (! iElementId || ! aSession->StorageL())
       
   478         {
       
   479         User::Leave(KErrNotReady);
       
   480         }
       
   481     
       
   482     TInt err = KErrNone;
       
   483     
       
   484     // First modify the link field which is the value in this field
       
   485     if (0 == iTarget->iValue)
       
   486     	{
       
   487     	/* The value of a linked field is modified to 0. This means that instead of storing
       
   488     	 * the 0 value the node (field) should be deleted from the DB.
       
   489     	 */
       
   490     	err = aSession->MaybeDeleteNodeL(NULL, iTarget->iElementId);
       
   491     	return err;
       
   492     	}
       
   493     else
       
   494     // Translate this link field into a storable element id <Table><Record> if enough information is present
       
   495         {
       
   496         SetLinkValueL(aSession->iOwner);
       
   497         }
       
   498         
       
   499     err = TMDBVisitor<TInt>::ModifyL(aSession, aAttributeFlags);
       
   500     
       
   501     if (iOwner->Type() == ELink &&
       
   502         err == KErrNone &&
       
   503         iLinkedRecord != NULL  &&  *iLinkedRecord != NULL  )
       
   504         {    
       
   505         // Now modify the linked record too.
       
   506 
       
   507         // it's the caller's responsibility to ensure the linkedRecord type matches the changed value
       
   508         CheckLinkedRecordL(iTarget->iValue);
       
   509         
       
   510         (*iLinkedRecord)->SetRecordId(iTarget->iValue);
       
   511 
       
   512         (*iLinkedRecord)->ModifyL(aSession->iOwner);
       
   513         }
       
   514         
       
   515         MaintainBCForLegacyLinks();
       
   516     
       
   517     	return err;
       
   518     }
       
   519 
       
   520  
       
   521 //EOF