diff -r e8e63152f320 -r 2a9601315dfc javaextensions/location/landmarks/src/clapilandmark.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaextensions/location/landmarks/src/clapilandmark.cpp Mon May 03 12:27:20 2010 +0300 @@ -0,0 +1,499 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implements a single Location API native landmark + * +*/ + + +// INTERNAL INCLUDES +#include "clapilandmark.h" +#include "clapiaddressinfo.h" +#include "mlapilandmarkstore.h" +#include "lapipanics.h" +#include "logger.h" +// EXTERNAL INCLUDES +#include +#include + +// UNNAMED LOCAL NAMESPACE +namespace +{ +// Number of the columns in the position field map +const TInt KLAPIPositionFieldMapColumnCount = 2; +// Address info field map which maps the Java address info +// fields and the native position fields which provide the same info +const TUint KLAPIPositionFieldMap[][KLAPIPositionFieldMapColumnCount] = +{ + { ELAPIAddressInfoExtension, EPositionFieldStreetExtension }, + { ELAPIAddressInfoStreet, EPositionFieldStreet }, + { ELAPIAddressInfoPostalCode, EPositionFieldPostalCode }, + { ELAPIAddressInfoCity, EPositionFieldCity }, + { ELAPIAddressInfoCounty, EPositionFieldCounty }, + { ELAPIAddressInfoState, EPositionFieldState }, + { ELAPIAddressInfoCountry, EPositionFieldCountry }, + { ELAPIAddressInfoCountryCode, EPositionFieldCountryCode }, + { ELAPIAddressInfoDistrict, EPositionFieldDistrict }, + { ELAPIAddressInfoBuildingName, EPositionFieldBuildingName }, + { ELAPIAddressInfoBuildingFloor, EPositionFieldBuildingFloor }, + { ELAPIAddressInfoBuildingRoom, EPositionFieldBuildingRoom }, + { ELAPIAddressInfoBuildingZone, EPositionFieldBuildingZone }, + { ELAPIAddressInfoCrossing1, EPositionFieldCrossing1 }, + { ELAPIAddressInfoCrossing2, EPositionFieldCrossing2 }, + { ELAPIAddressInfoUrl, EPositionFieldMediaLinksStart }, + { ELAPIAddressInfoPhoneNumber, EPositionFieldBuildingTelephone } +}; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::NewL +// --------------------------------------------------------------------------- +// +CLAPILandmark* CLAPILandmark::NewL(const TCtorParams& aParams) +{ + JELOG2(EJavaLocation); + CLAPILandmark* self = CLAPILandmark::NewLC(aParams); + CleanupStack::Pop(self); + return self; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::NewLC +// --------------------------------------------------------------------------- +// +CLAPILandmark* CLAPILandmark::NewLC(const TCtorParams& aParams) +{ + JELOG2(EJavaLocation); + CLAPILandmark* self = new(ELeave) CLAPILandmark(aParams); + CleanupStack::PushL(self); + self->ConstructL(); + return self; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +CLAPILandmark::~CLAPILandmark() +{ + JELOG2(EJavaLocation); + if (iLandmarkStore) + { + // Notify store that this landmark has been disposed + iLandmarkStore->LandmarkDisposed(*this); + } + + delete iAddressInfo; + delete iLandmarkName; + delete iDescription; + delete iCoordinates; + delete iLandmark; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +TLAPIItemId CLAPILandmark::Id() const +{ + JELOG2(EJavaLocation); + return iLandmark->LandmarkId(); +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +void CLAPILandmark::SetNameL(const TDesC& aName) +{ + JELOG2(EJavaLocation); + HBufC* name = aName.AllocL(); + delete iLandmarkName; + iLandmarkName = name; + iChangedAttributes |= ELAPILmAttrName; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +const TDesC& CLAPILandmark::NameL() +{ + JELOG2(EJavaLocation); + // Check that the name has been read from the native landmark store + // If not, then read the attribute and add it to the item + if (!iLandmarkName && !(iChangedAttributes & ELAPILmAttrName)) + { + TPtrC namePtr; + // Try to get the name from the native landmark + TInt err = iLandmark->GetLandmarkName(namePtr); + // The name could not be read. Try reading it from the store + if (err != KErrNone && iLandmarkStore && iLandmark->IsPartial()) + { + // Read the name attribute from the store + iLandmarkStore->ReadLandmarkAttributesL(*this, ELAPILmAttrName, + NULL); + // Store the name attribute to this landmark. The name attribute + // is added to the attributes of this landmark to indicate that the + // field has been read from the native landmark store. This should + // not return error since the name is always available after reading + err = iLandmark->GetLandmarkName(namePtr); + } + // The landmark name should be available now if the landmark is in a store + User::LeaveIfError(err); + iLandmarkName = namePtr.AllocL(); + } + + // If the name was not read (i.e it has not been set yet and + // this item does not belong to a database, return KNullDesC + return !iLandmarkName ? KNullDesC() : *iLandmarkName; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +void CLAPILandmark::SetDescriptionL(const TDesC* aDescription) +{ + JELOG2(EJavaLocation); + HBufC* description(NULL); + if (aDescription) + { + // The description must be concatenated because the API does not support + // throwing correct exceptions when handling too long descriptions + description = aDescription->Left(KPosLmMaxDescriptionLength).AllocL(); + } + + delete iDescription; + iDescription = description; + iChangedAttributes |= ELAPILmAttrDescription; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +const TDesC* CLAPILandmark::DescriptionL() +{ + JELOG2(EJavaLocation); + // Check that the description has been read from the native landmark store + // If not, then read the attribute and add it to the item + if (!iDescription && !(iChangedAttributes & ELAPILmAttrDescription)) + { + TPtrC descPtr; + // Try to get the description from the native landmark + TInt err = iLandmark->GetLandmarkDescription(descPtr); + // The description could not be read. Try reading it from the store + if (err != KErrNone && iLandmarkStore && iLandmark->IsPartial()) + { + // Read the name attribute from the store + iLandmarkStore->ReadLandmarkAttributesL(*this, + ELAPILmAttrDescription, NULL); + // Store the description attribute to this landmark. The attribute + // is added to the attributes of this landmark to indicate that the + // field has been read from the native landmark store. This should + // not return error since the field is always available after reading + err = iLandmark->GetLandmarkDescription(descPtr); + } + // The description should be available now if it has been set + if (err == KErrNone) + { + iDescription = descPtr.AllocL(); + } + } + + return iDescription; // Returns NULL if not found +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::SetCoordinatesL +// --------------------------------------------------------------------------- +// +void CLAPILandmark::SetCoordinatesL(const TLocality* aCoordinates) +{ + JELOG2(EJavaLocation); + TLocality* coordinates(NULL); + if (aCoordinates) + { + coordinates = new(ELeave) TLocality(*aCoordinates); + } + + delete iCoordinates; + iCoordinates = coordinates; + iChangedAttributes |= ELAPILmAttrPosition; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CoordinatesL +// --------------------------------------------------------------------------- +// +const TLocality* CLAPILandmark::CoordinatesL() +{ + JELOG2(EJavaLocation); + // Check that the position has been read from the native landmark store + // If not, then read the attribute and add it to the item + if (!iCoordinates && !(iChangedAttributes & ELAPILmAttrPosition)) + { + // First, try to get the position from the native item + TLocality loc; + TInt err = iLandmark->GetPosition(loc); + // The position has not been read. Try reading it from the store + if (err != KErrNone && iLandmarkStore && iLandmark->IsPartial()) + { + // Attributes must be read based on the previous ones + iLandmarkStore->ReadLandmarkAttributesL(*this, ELAPILmAttrPosition, + NULL); + // Store the position attribute to this landmark. The attribute + // is added to the attributes of this landmark to indicate that the + // field has been read from the native landmark store. This should + // not return error since the field is always available after reading + err = iLandmark->GetPosition(loc); + } + // The position should be available now if it has been set + if (err == KErrNone) + { + iCoordinates = new(ELeave) TLocality(loc); + } + } + + return iCoordinates; // Returns NULL if not found +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::SetAddressInfoL +// --------------------------------------------------------------------------- +// +void CLAPILandmark::SetAddressInfoL(CLAPIAddressInfo* aAddressInfo) +{ + JELOG2(EJavaLocation); + delete iAddressInfo; + iAddressInfo = aAddressInfo; + // Mark that the address information has been changed + iChangedAttributes |= ELAPILmAttrAddressInfo; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::AddressInfoL +// --------------------------------------------------------------------------- +// +const CLAPIAddressInfo* CLAPILandmark::AddressInfoL() +{ + JELOG2(EJavaLocation); + // Read the address information if it has not been read or set yet + if (!iAddressInfo && !(iChangedAttributes & ELAPILmAttrAddressInfo)) + { + iAddressInfo = CLAPIAddressInfo::NewL(); + RArray fields(ELAPINumAddressInfos); + CleanupClosePushL(fields); + // Add all supported address information fields to the array + // mapped to Landmarks API position field identifiers + for (TInt i = 0; i < ELAPINumAddressInfos; i++) + { + User::LeaveIfError(fields.Append(KLAPIPositionFieldMap[i][1])); + } + + // Try to get address information from the native landmark + TInt fieldCount = DoGetAddressInfoFieldValuesL(fields); + // Read the position fields from the native landmark store if the + // native landmark did not have any values in it and this landmark + // belongs to a landmark store + + // Note that reading high amount of position field data is very + // slow if the landmark has data in all fields + if (!fieldCount && iLandmarkStore && iLandmark->IsPartial()) + { + // Read supported position fields from the landmark store + iLandmarkStore->ReadLandmarkAttributesL(*this, ELAPILmNoAttributes, + &fields); + // Read the address information from the native landmark. The + // return value is ignored because we do not need it here + DoGetAddressInfoFieldValuesL(fields); + } + + CleanupStack::PopAndDestroy(&fields); + } + + return iAddressInfo; // Returns NULL if not found +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::PrepareForSaveL +// --------------------------------------------------------------------------- +// +void CLAPILandmark::PrepareForSaveL() +{ + JELOG2(EJavaLocation); + // Read full landmark from the store to prevent user data loss. There + // can be some fields which are not accessible using Location API and + // the data of external landmarks must not be lost + if (iLandmarkStore) + { + iLandmarkStore->ReadFullLandmarkL(*this); + } + + // Clear all attributes other than the name. The landmark should always have + // a name. Unchanged attributes must not be cleared since some other third + // party application may have changed those attributes already + iLandmark->RemoveLandmarkAttributes(iChangedAttributes & ~ELAPILmAttrName); + + if (iLandmarkName && iChangedAttributes & ELAPILmAttrName) + { + // The name of the landmark must not be too long when saving the entry + __ASSERT_ALWAYS(iLandmarkName->Length() <= KPosLmMaxTextFieldLength, + User::Leave(KErrArgument)); + // Set the name of the landmark. Note that it must never be empty + iLandmark->SetLandmarkNameL(*iLandmarkName); + } + + if (iDescription && iChangedAttributes & ELAPILmAttrDescription) + { + iLandmark->SetLandmarkDescriptionL(*iDescription); + } + + if (iCoordinates && iChangedAttributes & ELAPILmAttrPosition) + { + iLandmark->SetPositionL(*iCoordinates); + } + + if (iChangedAttributes & ELAPILmAttrAddressInfo) + { + // Store address info to the native landmark + for (TInt i = 0; i < ELAPINumAddressInfos; i++) + { + TUint32 positionField = KLAPIPositionFieldMap[i][1]; + if (!iAddressInfo || !iAddressInfo->Value(i + 1)) + { + // Clear the position field information if the address info + // array does not contain any data or the field is NULL + iLandmark->RemovePositionField(positionField); + } + else + { + const TDesC* value = iAddressInfo->Value(i + 1); + TPtrC truncatedValue = value->Left(KPosLmMaxTextFieldLength); + // The position field has been set so update the value + iLandmark->SetPositionFieldL(positionField, truncatedValue); + } + } + } + + // Note that category information is not added on purpose because + // this class is not responsible for handling the category information + + // All data is stored so reset changed attributes + iChangedAttributes = ELAPILmNoAttributes; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::PosLandmark +// --------------------------------------------------------------------------- +// +CPosLandmark& CLAPILandmark::PosLandmark() const +{ + JELOG2(EJavaLocation); + return *iLandmark; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::SetPosLandmark +// --------------------------------------------------------------------------- +// +void CLAPILandmark::SetPosLandmark(CPosLandmark* aLandmark) +{ + JELOG2(EJavaLocation); + delete iLandmark; + iLandmark = aLandmark; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::AssociateToStore +// --------------------------------------------------------------------------- +// +void CLAPILandmark::AssociateToStore(MLAPILandmarkStore* aLandmarkStore) +{ + JELOG2(EJavaLocation); + // This landmark has been associated to a different store + if (iLandmarkStore && iLandmarkStore != aLandmarkStore) + { + iLandmarkStore->LandmarkDisposed(*this); + } + + iLandmarkStore = aLandmarkStore; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::StoreClosed +// --------------------------------------------------------------------------- +// +void CLAPILandmark::StoreClosed() +{ + JELOG2(EJavaLocation); + iLandmarkStore = NULL; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::DoGetAddressInfoFieldValuesL +// --------------------------------------------------------------------------- +// +TInt CLAPILandmark::DoGetAddressInfoFieldValuesL(const RArray& aPositionFields) +{ + JELOG2(EJavaLocation); + // Address information should have been allocated before this + __ASSERT_DEBUG(iAddressInfo, LAPIError::Panic(ELAPIPanicNullArgument)); + TInt valueCount = 0; // The number of available position fields + + // Read the position field value from each supported address information field + TInt count = aPositionFields.Count(); + for (TInt i = 0; i < count; i++) + { + TPtrC fieldPtr; + // Get the position field from the native landmark. At this point, if + // the function returns an error, it indicates that there is no value + // in the specified positioning field. Use NULL to indicate that + TInt err = iLandmark->GetPositionField(aPositionFields[i], fieldPtr); + if (err == KErrNone) + { + iAddressInfo->SetValueL(i + 1, &fieldPtr); + valueCount++; + } + } + + return valueCount; +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::CLAPILandmark +// --------------------------------------------------------------------------- +// +CLAPILandmark::CLAPILandmark(const TCtorParams& aParams) : + iLandmarkStore(aParams.iLandmarkStore), iLandmark(aParams.iLandmark), + iChangedAttributes(ELAPILmNoAttributes) +{ + JELOG2(EJavaLocation); +} + +// --------------------------------------------------------------------------- +// CLAPILandmark::ConstructL +// --------------------------------------------------------------------------- +// +void CLAPILandmark::ConstructL() +{ + JELOG2(EJavaLocation); + // Check if this landmark is a new landmark + if (!iLandmark) + { + iLandmark = CPosLandmark::NewL(); + } +} + +// End of file