|
1 /* |
|
2 * Name : Loader.cpp |
|
3 * Description : |
|
4 * Project : This file is part of OpenMAR, an Open Mobile Augmented Reality browser |
|
5 * Website : http://OpenMAR.org |
|
6 * |
|
7 * Copyright (c) 2010 David Caabeiro |
|
8 * |
|
9 * All rights reserved. This program and the accompanying materials are made available |
|
10 * under the terms of the Eclipse Public License v1.0 which accompanies this |
|
11 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html |
|
12 * |
|
13 */ |
|
14 |
|
15 #include "Loader.h" |
|
16 |
|
17 #include "HttpClient.h" |
|
18 #include "Entry.h" |
|
19 |
|
20 #include <AknUtils.h> |
|
21 #include <LbsPositionInfo.h> |
|
22 #include <Http/mhttpdatasupplier.h> |
|
23 #include <HttpErr.h> |
|
24 |
|
25 #include <EPos_CPosLandmark.h> |
|
26 #include <utf.h> |
|
27 |
|
28 #include "Logger.h" |
|
29 |
|
30 CLoader* CLoader::NewL(MLandmarkLoaderObserver& aObserver) |
|
31 { |
|
32 CLoader* self = new(ELeave) CLoader(aObserver); |
|
33 CleanupStack::PushL(self); |
|
34 self->ConstructL(); |
|
35 CleanupStack::Pop(self); |
|
36 |
|
37 return self; |
|
38 } |
|
39 |
|
40 CLoader::~CLoader() |
|
41 { |
|
42 delete iEntry; |
|
43 delete iParser; |
|
44 delete iClient; |
|
45 } |
|
46 |
|
47 CLoader::CLoader(MLandmarkLoaderObserver& aObserver) |
|
48 : iObserver(aObserver) |
|
49 { |
|
50 } |
|
51 |
|
52 void CLoader::ConstructL() |
|
53 { |
|
54 LOGTXT("[GEONAMES] Creating POI loader"); |
|
55 |
|
56 iClient = CHttpClient::NewL(*this); |
|
57 |
|
58 _LIT8(KXmlMimeType, "text/xml"); |
|
59 iParser = Xml::CParser::NewL(KXmlMimeType, *this); |
|
60 |
|
61 iEntry = CEntry::NewL(); |
|
62 } |
|
63 |
|
64 void CLoader::RequestL(const TCoordinate& aPosition, TReal32 aRadius) |
|
65 { |
|
66 // Regardless of system locale, always use point as decimal separator character |
|
67 // Also use a maximum of 6 chars to represent each float |
|
68 TRealFormat realFormat; |
|
69 realFormat.iPoint = TChar('.'); |
|
70 realFormat.iWidth = 8; |
|
71 realFormat.iPlaces = 5; |
|
72 |
|
73 TBuf8<KDefaultRealWidth> latitude; |
|
74 latitude.Num(aPosition.Latitude(), realFormat); |
|
75 |
|
76 TBuf8<KDefaultRealWidth> longitude; |
|
77 longitude.Num(aPosition.Longitude(), realFormat); |
|
78 |
|
79 // Convert to kilometers |
|
80 const TInt radius = static_cast<TInt>(aRadius / 1000); |
|
81 |
|
82 TBuf8<2> langCode; |
|
83 |
|
84 // Use device's language to retrieve entries |
|
85 HBufC* tag = AknLangUtils::DisplayLanguageTagL(); |
|
86 langCode.Copy(tag->Left(2)); |
|
87 delete tag; |
|
88 |
|
89 // Set a limit to entries retrieved |
|
90 const TInt maxRows = 20; |
|
91 |
|
92 TBuf8<256> uri; |
|
93 _LIT8(KUri, "http://ws.geonames.org/findNearbyWikipedia?lat=%S&lng=%S&radius=%d&lang=%S&maxRows=%d"); |
|
94 uri.Format(KUri, &latitude, &longitude, radius, &langCode, maxRows); |
|
95 |
|
96 iClient->GetL(uri); |
|
97 } |
|
98 |
|
99 void CLoader::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent) |
|
100 { |
|
101 switch (aEvent.iStatus) |
|
102 { |
|
103 case THTTPEvent::EGotResponseHeaders: |
|
104 { |
|
105 RHTTPResponse resp = aTransaction.Response(); |
|
106 TInt status = resp.StatusCode(); |
|
107 |
|
108 // Treat any 2xx HTTP code as successful request |
|
109 TInt error = HTTPStatus::IsSuccessful(status)? KErrNone : KErrGeneral; |
|
110 |
|
111 if (error == KErrNone) |
|
112 iParser->ParseBeginL(); |
|
113 |
|
114 iObserver.LandmarkLoaderOpenedL(error); |
|
115 |
|
116 break; |
|
117 } |
|
118 |
|
119 case THTTPEvent::EGotResponseBodyData: |
|
120 { |
|
121 MHTTPDataSupplier* body = aTransaction.Response().Body(); |
|
122 |
|
123 TPtrC8 dataChunk; |
|
124 body->GetNextDataPart(dataChunk); |
|
125 iParser->ParseL(dataChunk); |
|
126 body->ReleaseData(); |
|
127 |
|
128 break; |
|
129 } |
|
130 |
|
131 case THTTPEvent::EResponseComplete: |
|
132 LOGTXT("[GEONAMES] HTTP response complete"); |
|
133 |
|
134 iParser->ParseEndL(); |
|
135 break ; |
|
136 |
|
137 case THTTPEvent::ESucceeded: |
|
138 case THTTPEvent::EFailed: |
|
139 { |
|
140 RHTTPResponse resp = aTransaction.Response(); |
|
141 TInt status = resp.StatusCode(); |
|
142 |
|
143 LOGARG("[GEONAMES] HTTP response status code %d", status); |
|
144 |
|
145 aTransaction.Close(); |
|
146 |
|
147 break; |
|
148 } |
|
149 |
|
150 default: |
|
151 LOGARG("[GEONAMES] HTTP unknown event %d", aEvent.iStatus); |
|
152 |
|
153 iObserver.LandmarkLoaderOpenedL(KErrUnknown); |
|
154 |
|
155 aTransaction.Close(); |
|
156 break; |
|
157 } |
|
158 } |
|
159 |
|
160 TInt CLoader::MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent) |
|
161 { |
|
162 return KErrNone; |
|
163 } |
|
164 |
|
165 void CLoader::OnStartDocumentL(const Xml::RDocumentParameters& aDocParam, TInt aErrorCode) |
|
166 {} |
|
167 |
|
168 void CLoader::OnEndDocumentL(TInt aErrorCode) |
|
169 {} |
|
170 |
|
171 void CLoader::OnStartElementL(const Xml::RTagInfo& aElement, const Xml::RAttributeArray& aAttributes, TInt aErrorCode) |
|
172 { |
|
173 _LIT8(KEntryTag, "entry"); |
|
174 if (aElement.LocalName().DesC() == KEntryTag) |
|
175 iState = EValid; |
|
176 else if (iState == EValid) |
|
177 iEntry->EnterState(aElement.LocalName().DesC()); |
|
178 } |
|
179 |
|
180 void CLoader::OnEndElementL(const Xml::RTagInfo& aElement, TInt aErrorCode) |
|
181 { |
|
182 _LIT8(KEntryTag, "entry"); |
|
183 if (aElement.LocalName().DesC() == KEntryTag) |
|
184 { |
|
185 NotifyPOIEntryL(); |
|
186 |
|
187 iEntry->Reset(); |
|
188 iState = EInvalid; |
|
189 } |
|
190 else |
|
191 iEntry->ExitState(); |
|
192 } |
|
193 |
|
194 void CLoader::OnContentL(const TDesC8& aBytes, TInt aErrorCode) |
|
195 { |
|
196 iEntry->FeedState(aBytes); |
|
197 } |
|
198 |
|
199 void CLoader::OnStartPrefixMappingL(const RString& /*aPrefix*/, const RString& /*aUri*/, TInt /*aErrorCode*/) |
|
200 {} |
|
201 |
|
202 void CLoader::OnEndPrefixMappingL(const RString& /*aPrefix*/, TInt /*aErrorCode*/) |
|
203 {} |
|
204 |
|
205 void CLoader::OnIgnorableWhiteSpaceL(const TDesC8& /*aBytes*/, TInt /*aErrorCode*/) |
|
206 {} |
|
207 |
|
208 void CLoader::OnSkippedEntityL(const RString& /*aName*/, TInt /*aErrorCode*/) |
|
209 {} |
|
210 |
|
211 void CLoader::OnProcessingInstructionL(const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt /*aErrorCode*/) |
|
212 {} |
|
213 |
|
214 void CLoader::OnError(TInt /*aErrorCode*/) |
|
215 {} |
|
216 |
|
217 TAny* CLoader::GetExtendedInterface(const TInt32 /*aUid*/) |
|
218 { |
|
219 return 0; |
|
220 } |
|
221 |
|
222 /* |
|
223 * Notify observer of new XML entry |
|
224 */ |
|
225 void CLoader::NotifyPOIEntryL() |
|
226 { |
|
227 CPosLandmark* landmark = CPosLandmark::NewLC(); |
|
228 |
|
229 HBufC* title = CnvUtfConverter::ConvertToUnicodeFromUtf8L(iEntry->iTitle); |
|
230 CleanupStack::PushL(title); |
|
231 landmark->SetLandmarkNameL(*title); |
|
232 CleanupStack::PopAndDestroy(title); |
|
233 |
|
234 HBufC* description = CnvUtfConverter::ConvertToUnicodeFromUtf8L(iEntry->iSummary); |
|
235 CleanupStack::PushL(description); |
|
236 landmark->SetLandmarkDescriptionL(*description); |
|
237 CleanupStack::PopAndDestroy(description); |
|
238 |
|
239 TLex8 lex; |
|
240 |
|
241 lex.Assign(iEntry->iLat); |
|
242 TReal32 lat = 0; |
|
243 lex.Val(lat); |
|
244 |
|
245 lex.Assign(iEntry->iLng); |
|
246 TReal32 lng = 0; |
|
247 lex.Val(lng); |
|
248 |
|
249 lex.Assign(iEntry->iElevation); |
|
250 TReal32 elevation = 0; |
|
251 lex.Val(elevation); |
|
252 |
|
253 TCoordinate coordinate(lat, lng, elevation); |
|
254 landmark->SetPositionL(TLocality(coordinate, 0, 0)); |
|
255 |
|
256 HBufC* url = HBufC::NewLC(iEntry->iWikipediaUrl.Length()); |
|
257 url->Des().Copy(iEntry->iWikipediaUrl); |
|
258 landmark->SetPositionFieldL(EPositionFieldMediaLinksStart, url->Left(KPosLmMaxTextFieldLength)); |
|
259 CleanupStack::PopAndDestroy(url); |
|
260 |
|
261 iObserver.LandmarkLoaderItemCreatedL(*landmark); |
|
262 |
|
263 CleanupStack::PopAndDestroy(landmark); |
|
264 } |