--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/location/landmarks/src/clapilandmark.cpp Tue Apr 27 16:30:29 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 <EPos_CPosLandmark.h>
+#include <lbsfields.h>
+
+// 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<TUint> 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<TUint>& 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