javaextensions/location/landmarks/src/clapilandmark.cpp
branchRCL_3
changeset 19 04becd199f91
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 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:  Implements a single Location API native landmark
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 // INTERNAL INCLUDES
       
    20 #include    "clapilandmark.h"
       
    21 #include    "clapiaddressinfo.h"
       
    22 #include    "mlapilandmarkstore.h"
       
    23 #include    "lapipanics.h"
       
    24 #include    "logger.h"
       
    25 // EXTERNAL INCLUDES
       
    26 #include    <EPos_CPosLandmark.h>
       
    27 #include    <lbsfields.h>
       
    28 
       
    29 // UNNAMED LOCAL NAMESPACE
       
    30 namespace
       
    31 {
       
    32 // Number of the columns in the position field map
       
    33 const TInt KLAPIPositionFieldMapColumnCount = 2;
       
    34 // Address info field map which maps the Java address info
       
    35 // fields and the native position fields which provide the same info
       
    36 const TUint KLAPIPositionFieldMap[][KLAPIPositionFieldMapColumnCount] =
       
    37 {
       
    38     { ELAPIAddressInfoExtension, EPositionFieldStreetExtension },
       
    39     { ELAPIAddressInfoStreet, EPositionFieldStreet },
       
    40     { ELAPIAddressInfoPostalCode, EPositionFieldPostalCode },
       
    41     { ELAPIAddressInfoCity, EPositionFieldCity },
       
    42     { ELAPIAddressInfoCounty, EPositionFieldCounty },
       
    43     { ELAPIAddressInfoState, EPositionFieldState },
       
    44     { ELAPIAddressInfoCountry, EPositionFieldCountry },
       
    45     { ELAPIAddressInfoCountryCode, EPositionFieldCountryCode },
       
    46     { ELAPIAddressInfoDistrict, EPositionFieldDistrict },
       
    47     { ELAPIAddressInfoBuildingName, EPositionFieldBuildingName },
       
    48     { ELAPIAddressInfoBuildingFloor, EPositionFieldBuildingFloor },
       
    49     { ELAPIAddressInfoBuildingRoom, EPositionFieldBuildingRoom },
       
    50     { ELAPIAddressInfoBuildingZone, EPositionFieldBuildingZone },
       
    51     { ELAPIAddressInfoCrossing1, EPositionFieldCrossing1 },
       
    52     { ELAPIAddressInfoCrossing2, EPositionFieldCrossing2 },
       
    53     { ELAPIAddressInfoUrl, EPositionFieldMediaLinksStart },
       
    54     { ELAPIAddressInfoPhoneNumber, EPositionFieldBuildingTelephone }
       
    55 };
       
    56 }
       
    57 
       
    58 // ---------------------------------------------------------------------------
       
    59 // CLAPILandmark::NewL
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 CLAPILandmark* CLAPILandmark::NewL(const TCtorParams& aParams)
       
    63 {
       
    64     JELOG2(EJavaLocation);
       
    65     CLAPILandmark* self = CLAPILandmark::NewLC(aParams);
       
    66     CleanupStack::Pop(self);
       
    67     return self;
       
    68 }
       
    69 
       
    70 // ---------------------------------------------------------------------------
       
    71 // CLAPILandmark::NewLC
       
    72 // ---------------------------------------------------------------------------
       
    73 //
       
    74 CLAPILandmark* CLAPILandmark::NewLC(const TCtorParams& aParams)
       
    75 {
       
    76     JELOG2(EJavaLocation);
       
    77     CLAPILandmark* self = new(ELeave) CLAPILandmark(aParams);
       
    78     CleanupStack::PushL(self);
       
    79     self->ConstructL();
       
    80     return self;
       
    81 }
       
    82 
       
    83 // ---------------------------------------------------------------------------
       
    84 // CLAPILandmark::CLAPILandmark
       
    85 // ---------------------------------------------------------------------------
       
    86 //
       
    87 CLAPILandmark::~CLAPILandmark()
       
    88 {
       
    89     JELOG2(EJavaLocation);
       
    90     if (iLandmarkStore)
       
    91     {
       
    92         // Notify store that this landmark has been disposed
       
    93         iLandmarkStore->LandmarkDisposed(*this);
       
    94     }
       
    95 
       
    96     delete iAddressInfo;
       
    97     delete iLandmarkName;
       
    98     delete iDescription;
       
    99     delete iCoordinates;
       
   100     delete iLandmark;
       
   101 }
       
   102 
       
   103 // ---------------------------------------------------------------------------
       
   104 // CLAPILandmark::CLAPILandmark
       
   105 // ---------------------------------------------------------------------------
       
   106 //
       
   107 TLAPIItemId CLAPILandmark::Id() const
       
   108 {
       
   109     JELOG2(EJavaLocation);
       
   110     return iLandmark->LandmarkId();
       
   111 }
       
   112 
       
   113 // ---------------------------------------------------------------------------
       
   114 // CLAPILandmark::CLAPILandmark
       
   115 // ---------------------------------------------------------------------------
       
   116 //
       
   117 void CLAPILandmark::SetNameL(const TDesC& aName)
       
   118 {
       
   119     JELOG2(EJavaLocation);
       
   120     HBufC* name = aName.AllocL();
       
   121     delete iLandmarkName;
       
   122     iLandmarkName = name;
       
   123     iChangedAttributes |= ELAPILmAttrName;
       
   124 }
       
   125 
       
   126 // ---------------------------------------------------------------------------
       
   127 // CLAPILandmark::CLAPILandmark
       
   128 // ---------------------------------------------------------------------------
       
   129 //
       
   130 const TDesC& CLAPILandmark::NameL()
       
   131 {
       
   132     JELOG2(EJavaLocation);
       
   133     // Check that the name has been read from the native landmark store
       
   134     // If not, then read the attribute and add it to the item
       
   135     if (!iLandmarkName && !(iChangedAttributes & ELAPILmAttrName))
       
   136     {
       
   137         TPtrC namePtr;
       
   138         // Try to get the name from the native landmark
       
   139         TInt err = iLandmark->GetLandmarkName(namePtr);
       
   140         // The name could not be read. Try reading it from the store
       
   141         if (err != KErrNone && iLandmarkStore && iLandmark->IsPartial())
       
   142         {
       
   143             // Read the name attribute from the store
       
   144             iLandmarkStore->ReadLandmarkAttributesL(*this, ELAPILmAttrName,
       
   145                                                     NULL);
       
   146             // Store the name attribute to this landmark. The name attribute
       
   147             // is added to the attributes of this landmark to indicate that the
       
   148             // field has been read from the native landmark store. This should
       
   149             // not return error since the name is always available after reading
       
   150             err = iLandmark->GetLandmarkName(namePtr);
       
   151         }
       
   152         // The landmark name should be available now if the landmark is in a store
       
   153         User::LeaveIfError(err);
       
   154         iLandmarkName = namePtr.AllocL();
       
   155     }
       
   156 
       
   157     // If the name was not read (i.e it has not been set yet and
       
   158     // this item does not belong to a database, return KNullDesC
       
   159     return !iLandmarkName ? KNullDesC() : *iLandmarkName;
       
   160 }
       
   161 
       
   162 // ---------------------------------------------------------------------------
       
   163 // CLAPILandmark::CLAPILandmark
       
   164 // ---------------------------------------------------------------------------
       
   165 //
       
   166 void CLAPILandmark::SetDescriptionL(const TDesC* aDescription)
       
   167 {
       
   168     JELOG2(EJavaLocation);
       
   169     HBufC* description(NULL);
       
   170     if (aDescription)
       
   171     {
       
   172         // The description must be concatenated because the API does not support
       
   173         // throwing correct exceptions when handling too long descriptions
       
   174         description = aDescription->Left(KPosLmMaxDescriptionLength).AllocL();
       
   175     }
       
   176 
       
   177     delete iDescription;
       
   178     iDescription = description;
       
   179     iChangedAttributes |= ELAPILmAttrDescription;
       
   180 }
       
   181 
       
   182 // ---------------------------------------------------------------------------
       
   183 // CLAPILandmark::CLAPILandmark
       
   184 // ---------------------------------------------------------------------------
       
   185 //
       
   186 const TDesC* CLAPILandmark::DescriptionL()
       
   187 {
       
   188     JELOG2(EJavaLocation);
       
   189     // Check that the description has been read from the native landmark store
       
   190     // If not, then read the attribute and add it to the item
       
   191     if (!iDescription && !(iChangedAttributes & ELAPILmAttrDescription))
       
   192     {
       
   193         TPtrC descPtr;
       
   194         // Try to get the description from the native landmark
       
   195         TInt err = iLandmark->GetLandmarkDescription(descPtr);
       
   196         // The description could not be read. Try reading it from the store
       
   197         if (err != KErrNone && iLandmarkStore && iLandmark->IsPartial())
       
   198         {
       
   199             // Read the name attribute from the store
       
   200             iLandmarkStore->ReadLandmarkAttributesL(*this,
       
   201                                                     ELAPILmAttrDescription, NULL);
       
   202             // Store the description attribute to this landmark. The  attribute
       
   203             // is added to the attributes of this landmark to indicate that the
       
   204             // field has been read from the native landmark store. This should
       
   205             // not return error since the field is always available after reading
       
   206             err = iLandmark->GetLandmarkDescription(descPtr);
       
   207         }
       
   208         // The description should be available now if it has been set
       
   209         if (err == KErrNone)
       
   210         {
       
   211             iDescription = descPtr.AllocL();
       
   212         }
       
   213     }
       
   214 
       
   215     return iDescription; // Returns NULL if not found
       
   216 }
       
   217 
       
   218 // ---------------------------------------------------------------------------
       
   219 // CLAPILandmark::SetCoordinatesL
       
   220 // ---------------------------------------------------------------------------
       
   221 //
       
   222 void CLAPILandmark::SetCoordinatesL(const TLocality* aCoordinates)
       
   223 {
       
   224     JELOG2(EJavaLocation);
       
   225     TLocality* coordinates(NULL);
       
   226     if (aCoordinates)
       
   227     {
       
   228         coordinates = new(ELeave) TLocality(*aCoordinates);
       
   229     }
       
   230 
       
   231     delete iCoordinates;
       
   232     iCoordinates = coordinates;
       
   233     iChangedAttributes |= ELAPILmAttrPosition;
       
   234 }
       
   235 
       
   236 // ---------------------------------------------------------------------------
       
   237 // CLAPILandmark::CoordinatesL
       
   238 // ---------------------------------------------------------------------------
       
   239 //
       
   240 const TLocality* CLAPILandmark::CoordinatesL()
       
   241 {
       
   242     JELOG2(EJavaLocation);
       
   243     // Check that the position has been read from the native landmark store
       
   244     // If not, then read the attribute and add it to the item
       
   245     if (!iCoordinates && !(iChangedAttributes & ELAPILmAttrPosition))
       
   246     {
       
   247         // First, try to get the position from the native item
       
   248         TLocality loc;
       
   249         TInt err = iLandmark->GetPosition(loc);
       
   250         // The position has not been read. Try reading it from the store
       
   251         if (err != KErrNone && iLandmarkStore && iLandmark->IsPartial())
       
   252         {
       
   253             // Attributes must be read based on the previous ones
       
   254             iLandmarkStore->ReadLandmarkAttributesL(*this, ELAPILmAttrPosition,
       
   255                                                     NULL);
       
   256             // Store the position attribute to this landmark. The  attribute
       
   257             // is added to the attributes of this landmark to indicate that the
       
   258             // field has been read from the native landmark store. This should
       
   259             // not return error since the field is always available after reading
       
   260             err = iLandmark->GetPosition(loc);
       
   261         }
       
   262         // The position should be available now if it has been set
       
   263         if (err == KErrNone)
       
   264         {
       
   265             iCoordinates = new(ELeave) TLocality(loc);
       
   266         }
       
   267     }
       
   268 
       
   269     return iCoordinates; // Returns NULL if not found
       
   270 }
       
   271 
       
   272 // ---------------------------------------------------------------------------
       
   273 // CLAPILandmark::SetAddressInfoL
       
   274 // ---------------------------------------------------------------------------
       
   275 //
       
   276 void CLAPILandmark::SetAddressInfoL(CLAPIAddressInfo* aAddressInfo)
       
   277 {
       
   278     JELOG2(EJavaLocation);
       
   279     delete iAddressInfo;
       
   280     iAddressInfo = aAddressInfo;
       
   281     // Mark that the address information has been changed
       
   282     iChangedAttributes |= ELAPILmAttrAddressInfo;
       
   283 }
       
   284 
       
   285 // ---------------------------------------------------------------------------
       
   286 // CLAPILandmark::AddressInfoL
       
   287 // ---------------------------------------------------------------------------
       
   288 //
       
   289 const CLAPIAddressInfo* CLAPILandmark::AddressInfoL()
       
   290 {
       
   291     JELOG2(EJavaLocation);
       
   292     // Read the address information if it has not been read or set yet
       
   293     if (!iAddressInfo && !(iChangedAttributes & ELAPILmAttrAddressInfo))
       
   294     {
       
   295         iAddressInfo = CLAPIAddressInfo::NewL();
       
   296         RArray<TUint> fields(ELAPINumAddressInfos);
       
   297         CleanupClosePushL(fields);
       
   298         // Add all supported address information fields to the array
       
   299         // mapped to Landmarks API position field identifiers
       
   300         for (TInt i = 0; i < ELAPINumAddressInfos; i++)
       
   301         {
       
   302             User::LeaveIfError(fields.Append(KLAPIPositionFieldMap[i][1]));
       
   303         }
       
   304 
       
   305         // Try to get address information from the native landmark
       
   306         TInt fieldCount = DoGetAddressInfoFieldValuesL(fields);
       
   307         // Read the position fields from the native landmark store if the
       
   308         // native landmark did not have any values in it and this landmark
       
   309         // belongs to a landmark store
       
   310 
       
   311         // Note that reading high amount of position field data is very
       
   312         // slow if the landmark has data in all fields
       
   313         if (!fieldCount && iLandmarkStore && iLandmark->IsPartial())
       
   314         {
       
   315             // Read supported position fields from the landmark store
       
   316             iLandmarkStore->ReadLandmarkAttributesL(*this, ELAPILmNoAttributes,
       
   317                                                     &fields);
       
   318             // Read the address information from the native landmark. The
       
   319             // return value is ignored because we do not need it here
       
   320             DoGetAddressInfoFieldValuesL(fields);
       
   321         }
       
   322 
       
   323         CleanupStack::PopAndDestroy(&fields);
       
   324     }
       
   325 
       
   326     return iAddressInfo; // Returns NULL if not found
       
   327 }
       
   328 
       
   329 // ---------------------------------------------------------------------------
       
   330 // CLAPILandmark::PrepareForSaveL
       
   331 // ---------------------------------------------------------------------------
       
   332 //
       
   333 void CLAPILandmark::PrepareForSaveL()
       
   334 {
       
   335     JELOG2(EJavaLocation);
       
   336     // Read full landmark from the store to prevent user data loss. There
       
   337     // can be some fields which are not accessible using Location API and
       
   338     // the data of external landmarks must not be lost
       
   339     if (iLandmarkStore)
       
   340     {
       
   341         iLandmarkStore->ReadFullLandmarkL(*this);
       
   342     }
       
   343 
       
   344     // Clear all attributes other than the name. The landmark should always have
       
   345     // a name. Unchanged attributes must not be cleared since some other third
       
   346     // party application may have changed those attributes already
       
   347     iLandmark->RemoveLandmarkAttributes(iChangedAttributes & ~ELAPILmAttrName);
       
   348 
       
   349     if (iLandmarkName && iChangedAttributes & ELAPILmAttrName)
       
   350     {
       
   351         // The name of the landmark must not be too long when saving the entry
       
   352         __ASSERT_ALWAYS(iLandmarkName->Length() <= KPosLmMaxTextFieldLength,
       
   353                         User::Leave(KErrArgument));
       
   354         // Set the name of the landmark. Note that it must never be empty
       
   355         iLandmark->SetLandmarkNameL(*iLandmarkName);
       
   356     }
       
   357 
       
   358     if (iDescription && iChangedAttributes & ELAPILmAttrDescription)
       
   359     {
       
   360         iLandmark->SetLandmarkDescriptionL(*iDescription);
       
   361     }
       
   362 
       
   363     if (iCoordinates && iChangedAttributes & ELAPILmAttrPosition)
       
   364     {
       
   365         iLandmark->SetPositionL(*iCoordinates);
       
   366     }
       
   367 
       
   368     if (iChangedAttributes & ELAPILmAttrAddressInfo)
       
   369     {
       
   370         // Store address info to the native landmark
       
   371         for (TInt i = 0; i < ELAPINumAddressInfos; i++)
       
   372         {
       
   373             TUint32 positionField = KLAPIPositionFieldMap[i][1];
       
   374             if (!iAddressInfo || !iAddressInfo->Value(i + 1))
       
   375             {
       
   376                 // Clear the position field information if the address info
       
   377                 // array does not contain any data or the field is NULL
       
   378                 iLandmark->RemovePositionField(positionField);
       
   379             }
       
   380             else
       
   381             {
       
   382                 const TDesC* value = iAddressInfo->Value(i + 1);
       
   383                 TPtrC truncatedValue = value->Left(KPosLmMaxTextFieldLength);
       
   384                 // The position field has been set so update the value
       
   385                 iLandmark->SetPositionFieldL(positionField, truncatedValue);
       
   386             }
       
   387         }
       
   388     }
       
   389 
       
   390     // Note that category information is not added on purpose because
       
   391     // this class is not responsible for handling the category information
       
   392 
       
   393     // All data is stored so reset changed attributes
       
   394     iChangedAttributes = ELAPILmNoAttributes;
       
   395 }
       
   396 
       
   397 // ---------------------------------------------------------------------------
       
   398 // CLAPILandmark::PosLandmark
       
   399 // ---------------------------------------------------------------------------
       
   400 //
       
   401 CPosLandmark& CLAPILandmark::PosLandmark() const
       
   402 {
       
   403     JELOG2(EJavaLocation);
       
   404     return *iLandmark;
       
   405 }
       
   406 
       
   407 // ---------------------------------------------------------------------------
       
   408 // CLAPILandmark::SetPosLandmark
       
   409 // ---------------------------------------------------------------------------
       
   410 //
       
   411 void CLAPILandmark::SetPosLandmark(CPosLandmark* aLandmark)
       
   412 {
       
   413     JELOG2(EJavaLocation);
       
   414     delete iLandmark;
       
   415     iLandmark = aLandmark;
       
   416 }
       
   417 
       
   418 // ---------------------------------------------------------------------------
       
   419 // CLAPILandmark::AssociateToStore
       
   420 // ---------------------------------------------------------------------------
       
   421 //
       
   422 void CLAPILandmark::AssociateToStore(MLAPILandmarkStore* aLandmarkStore)
       
   423 {
       
   424     JELOG2(EJavaLocation);
       
   425     // This landmark has been associated to a different store
       
   426     if (iLandmarkStore && iLandmarkStore != aLandmarkStore)
       
   427     {
       
   428         iLandmarkStore->LandmarkDisposed(*this);
       
   429     }
       
   430 
       
   431     iLandmarkStore = aLandmarkStore;
       
   432 }
       
   433 
       
   434 // ---------------------------------------------------------------------------
       
   435 // CLAPILandmark::StoreClosed
       
   436 // ---------------------------------------------------------------------------
       
   437 //
       
   438 void CLAPILandmark::StoreClosed()
       
   439 {
       
   440     JELOG2(EJavaLocation);
       
   441     iLandmarkStore = NULL;
       
   442 }
       
   443 
       
   444 // ---------------------------------------------------------------------------
       
   445 // CLAPILandmark::DoGetAddressInfoFieldValuesL
       
   446 // ---------------------------------------------------------------------------
       
   447 //
       
   448 TInt CLAPILandmark::DoGetAddressInfoFieldValuesL(const RArray<TUint>& aPositionFields)
       
   449 {
       
   450     JELOG2(EJavaLocation);
       
   451     // Address information should have been allocated before this
       
   452     __ASSERT_DEBUG(iAddressInfo, LAPIError::Panic(ELAPIPanicNullArgument));
       
   453     TInt valueCount = 0; // The number of available position fields
       
   454 
       
   455     // Read the position field value from each supported address information field
       
   456     TInt count = aPositionFields.Count();
       
   457     for (TInt i = 0; i < count; i++)
       
   458     {
       
   459         TPtrC fieldPtr;
       
   460         // Get the position field from the native landmark. At this point, if
       
   461         // the function returns an error, it indicates that there is no value
       
   462         // in the specified positioning field. Use NULL to indicate that
       
   463         TInt err = iLandmark->GetPositionField(aPositionFields[i], fieldPtr);
       
   464         if (err == KErrNone)
       
   465         {
       
   466             iAddressInfo->SetValueL(i + 1, &fieldPtr);
       
   467             valueCount++;
       
   468         }
       
   469     }
       
   470 
       
   471     return valueCount;
       
   472 }
       
   473 
       
   474 // ---------------------------------------------------------------------------
       
   475 // CLAPILandmark::CLAPILandmark
       
   476 // ---------------------------------------------------------------------------
       
   477 //
       
   478 CLAPILandmark::CLAPILandmark(const TCtorParams& aParams) :
       
   479         iLandmarkStore(aParams.iLandmarkStore), iLandmark(aParams.iLandmark),
       
   480         iChangedAttributes(ELAPILmNoAttributes)
       
   481 {
       
   482     JELOG2(EJavaLocation);
       
   483 }
       
   484 
       
   485 // ---------------------------------------------------------------------------
       
   486 // CLAPILandmark::ConstructL
       
   487 // ---------------------------------------------------------------------------
       
   488 //
       
   489 void CLAPILandmark::ConstructL()
       
   490 {
       
   491     JELOG2(EJavaLocation);
       
   492     // Check if this landmark is a new landmark
       
   493     if (!iLandmark)
       
   494     {
       
   495         iLandmark = CPosLandmark::NewL();
       
   496     }
       
   497 }
       
   498 
       
   499 // End of file