1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
5 * Author: Mateusz Loskot, mateusz@loskot.net
6 *
7 ******************************************************************************
8 * Copyright (c) 2007, Mateusz Loskot
9 * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include <algorithm>
31
32 #if !DEBUG_JSON
33 # ifdef __clang__
34 # pragma clang diagnostic push
35 # pragma clang diagnostic ignored "-Wunknown-pragmas"
36 # pragma clang diagnostic ignored "-Wdocumentation"
37 # endif
38 #endif // !DEBUG_VERBOSE
39
40 #include <json.h>
41
42 #if !DEBUG_JSON
43 # ifdef __clang
44 # pragma clang diagnostic pop
45 # endif
46 #endif // !DEBUG_VERBOSE
47
48 #include "ogr_geojson.h"
49 #include "ogrgeojsonreader.h"
50
51 CPL_CVSID("$Id: ogrgeojsonlayer.cpp 245fbcca246f2fd183176dcacd68e3b4e98622df 2020-01-07 04:30:14 -0700 Sean Gillies $")
52
53 /************************************************************************/
54 /* STATIC MEMBERS DEFINITION */
55 /************************************************************************/
56
57 const char* const OGRGeoJSONLayer::DefaultName = "OGRGeoJSON";
58 const OGRwkbGeometryType OGRGeoJSONLayer::DefaultGeometryType = wkbUnknown;
59
60 /************************************************************************/
61 /* OGRGeoJSONLayer */
62 /************************************************************************/
63
OGRGeoJSONLayer(const char * pszName,OGRSpatialReference * poSRSIn,OGRwkbGeometryType eGType,OGRGeoJSONDataSource * poDS,OGRGeoJSONReader * poReader)64 OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
65 OGRSpatialReference* poSRSIn,
66 OGRwkbGeometryType eGType,
67 OGRGeoJSONDataSource* poDS,
68 OGRGeoJSONReader* poReader ):
69 OGRMemLayer( pszName, poSRSIn, eGType),
70 poDS_(poDS),
71 poReader_(poReader),
72 bHasAppendedFeatures_(false),
73 bUpdated_(false),
74 bOriginalIdModified_(false),
75 nTotalFeatureCount_(0),
76 nNextFID_(0)
77 {
78 SetAdvertizeUTF8(true);
79 SetUpdatable( poDS->IsUpdatable() );
80 }
81
82 /************************************************************************/
83 /* ~OGRGeoJSONLayer */
84 /************************************************************************/
85
~OGRGeoJSONLayer()86 OGRGeoJSONLayer::~OGRGeoJSONLayer()
87 {
88 TerminateAppendSession();
89 delete poReader_;
90 }
91
92 /************************************************************************/
93 /* TerminateAppendSession() */
94 /************************************************************************/
95
TerminateAppendSession()96 void OGRGeoJSONLayer::TerminateAppendSession()
97 {
98 if( bHasAppendedFeatures_ )
99 {
100 VSILFILE* fp = poReader_->GetFP();
101 VSIFPrintfL(fp, "\n]\n}\n");
102 VSIFFlushL(fp);
103 bHasAppendedFeatures_ = false;
104 }
105 }
106
107 /************************************************************************/
108 /* GetFIDColumn */
109 /************************************************************************/
110
GetFIDColumn()111 const char* OGRGeoJSONLayer::GetFIDColumn()
112 {
113 return sFIDColumn_.c_str();
114 }
115
116 /************************************************************************/
117 /* SetFIDColumn */
118 /************************************************************************/
119
SetFIDColumn(const char * pszFIDColumn)120 void OGRGeoJSONLayer::SetFIDColumn( const char* pszFIDColumn )
121 {
122 sFIDColumn_ = pszFIDColumn;
123 }
124
125 /************************************************************************/
126 /* ResetReading() */
127 /************************************************************************/
128
ResetReading()129 void OGRGeoJSONLayer::ResetReading()
130 {
131 nFeatureReadSinceReset_ = 0;
132 if( poReader_ )
133 {
134 TerminateAppendSession();
135 nNextFID_ = 0;
136 poReader_->ResetReading();
137 }
138 else
139 OGRMemLayer::ResetReading();
140 }
141
142 /************************************************************************/
143 /* GetNextFeature() */
144 /************************************************************************/
145
GetNextFeature()146 OGRFeature* OGRGeoJSONLayer::GetNextFeature()
147 {
148 if( poReader_ )
149 {
150 if( bHasAppendedFeatures_ )
151 {
152 ResetReading();
153 }
154 while ( true )
155 {
156 OGRFeature* poFeature = poReader_->GetNextFeature(this);
157 if( poFeature == nullptr )
158 return nullptr;
159 if( poFeature->GetFID() == OGRNullFID )
160 {
161 poFeature->SetFID(nNextFID_);
162 nNextFID_ ++;
163 }
164 if( (m_poFilterGeom == nullptr ||
165 FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter)) )
166 && (m_poAttrQuery == nullptr ||
167 m_poAttrQuery->Evaluate(poFeature)) )
168 {
169 nFeatureReadSinceReset_ ++;
170 return poFeature;
171 }
172 delete poFeature;
173 }
174 }
175 else
176 {
177 auto ret = OGRMemLayer::GetNextFeature();
178 if( ret )
179 {
180 nFeatureReadSinceReset_ ++;
181 }
182 return ret;
183 }
184 }
185
186 /************************************************************************/
187 /* GetFeatureCount() */
188 /************************************************************************/
189
GetFeatureCount(int bForce)190 GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
191 {
192 if( poReader_ )
193 {
194 if( m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
195 nTotalFeatureCount_ >= 0 )
196 {
197 return nTotalFeatureCount_;
198 }
199 return OGRLayer::GetFeatureCount(bForce);
200 }
201 else
202 {
203 return OGRMemLayer::GetFeatureCount(bForce);
204 }
205 }
206
207 /************************************************************************/
208 /* GetFeature() */
209 /************************************************************************/
210
GetFeature(GIntBig nFID)211 OGRFeature* OGRGeoJSONLayer::GetFeature(GIntBig nFID)
212 {
213 if( poReader_ )
214 {
215 if( !IsUpdatable() )
216 {
217 return poReader_->GetFeature(this, nFID);
218 }
219 return OGRLayer::GetFeature(nFID);
220 }
221 else
222 {
223 return OGRMemLayer::GetFeature(nFID);
224 }
225 }
226
227 /************************************************************************/
228 /* IngestAll() */
229 /************************************************************************/
230
IngestAll()231 bool OGRGeoJSONLayer::IngestAll()
232 {
233 if( poReader_ )
234 {
235 TerminateAppendSession();
236
237 OGRGeoJSONReader* poReader = poReader_;
238 poReader_ = nullptr;
239
240 nNextFID_ = 0;
241 nTotalFeatureCount_ = -1;
242 bool bRet = poReader->IngestAll(this);
243 delete poReader;
244 return bRet;
245 }
246 else
247 {
248 return true;
249 }
250 }
251
252 /************************************************************************/
253 /* ISetFeature() */
254 /************************************************************************/
255
ISetFeature(OGRFeature * poFeature)256 OGRErr OGRGeoJSONLayer::ISetFeature( OGRFeature *poFeature )
257 {
258 if( !IsUpdatable() )
259 return OGRERR_FAILURE;
260 if( poReader_ )
261 {
262 auto nNextIndex = nFeatureReadSinceReset_;
263 if( !IngestAll() )
264 return OGRERR_FAILURE;
265 SetNextByIndex(nNextIndex);
266 }
267 return OGRMemLayer::ISetFeature(poFeature);
268 }
269
270 /************************************************************************/
271 /* ICreateFeature() */
272 /************************************************************************/
273
ICreateFeature(OGRFeature * poFeature)274 OGRErr OGRGeoJSONLayer::ICreateFeature( OGRFeature *poFeature )
275 {
276 if( !IsUpdatable() )
277 return OGRERR_FAILURE;
278 if( poReader_ )
279 {
280 bool bTryEasyAppend = true;
281 while( true )
282 {
283 // We can trivially append to end of existing file, provided the
284 // following conditions are met:
285 // * the "features" array member is the last one of the main
286 // object (poReader_->CanEasilyAppend())
287 // * there is no "bbox" at feature collection level (could possibly
288 // be supported)
289 // * the features have no explicit FID field, so it is trivial to
290 // derive the FID of newly created features without collision
291 // * we know the total number of existing features
292 if( bTryEasyAppend &&
293 poReader_->CanEasilyAppend() && !poReader_->FCHasBBOX() &&
294 sFIDColumn_.empty() &&
295 GetLayerDefn()->GetFieldIndex("id") < 0 &&
296 nTotalFeatureCount_ >= 0 )
297 {
298 VSILFILE* fp = poReader_->GetFP();
299 if( !bHasAppendedFeatures_ )
300 {
301 // Locate "} ] }" (or "[ ] }") pattern at end of file
302 VSIFSeekL(fp, 0, SEEK_END);
303 vsi_l_offset nOffset = VSIFTellL(fp);
304 nOffset -= 10;
305 VSIFSeekL(fp, nOffset, SEEK_SET);
306 char szBuffer[11];
307 VSIFReadL(szBuffer, 10, 1, fp);
308 szBuffer[10] = 0;
309 int i = 9;
310 // Locate final }
311 while( isspace(szBuffer[i]) && i > 0 )
312 i --;
313 if( szBuffer[i] != '}' )
314 {
315 bTryEasyAppend = false;
316 continue;
317 }
318 if( i > 0 )
319 i --;
320 // Locate ']' ending features array
321 while( isspace(szBuffer[i]) && i > 0 )
322 i --;
323 if( szBuffer[i] != ']' )
324 {
325 bTryEasyAppend = false;
326 continue;
327 }
328 if( i > 0 )
329 i --;
330 while( isspace(szBuffer[i]) && i > 0 )
331 i --;
332 // Locate '}' ending last feature, or '[' starting features
333 // array
334 if( szBuffer[i] != '}' && szBuffer[i] != '[' )
335 {
336 bTryEasyAppend = false;
337 continue;
338 }
339 bool bExistingFeature = szBuffer[i] == '}';
340 nOffset += i + 1;
341 VSIFSeekL(fp, nOffset, SEEK_SET);
342 if( bExistingFeature )
343 {
344 VSIFPrintfL(fp, ",");
345 }
346 VSIFPrintfL(fp, "\n");
347 bHasAppendedFeatures_ = true;
348 }
349 else
350 {
351 VSIFPrintfL(fp, ",\n");
352 }
353 json_object* poObj =
354 OGRGeoJSONWriteFeature( poFeature, OGRGeoJSONWriteOptions() );
355 VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) );
356 json_object_put( poObj );
357
358 if( poFeature->GetFID() == OGRNullFID )
359 {
360 poFeature->SetFID(nTotalFeatureCount_);
361 }
362 nTotalFeatureCount_ ++;
363
364 return OGRERR_NONE;
365 }
366 else if( IngestAll() )
367 {
368 break;
369 }
370 else
371 {
372 return OGRERR_FAILURE;
373 }
374 }
375 }
376 return OGRMemLayer::ICreateFeature(poFeature);
377 }
378
379 /************************************************************************/
380 /* DeleteFeature() */
381 /************************************************************************/
382
DeleteFeature(GIntBig nFID)383 OGRErr OGRGeoJSONLayer::DeleteFeature( GIntBig nFID )
384 {
385 if( !IsUpdatable() || !IngestAll() )
386 return OGRERR_FAILURE;
387 return OGRMemLayer::DeleteFeature(nFID);
388 }
389
390 /************************************************************************/
391 /* CreateField() */
392 /************************************************************************/
393
CreateField(OGRFieldDefn * poField,int bApproxOK)394 OGRErr OGRGeoJSONLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
395 {
396 if( !IsUpdatable() || !IngestAll() )
397 return OGRERR_FAILURE;
398 return OGRMemLayer::CreateField(poField, bApproxOK);
399 }
400
401 /************************************************************************/
402 /* DeleteField() */
403 /************************************************************************/
404
DeleteField(int iField)405 OGRErr OGRGeoJSONLayer::DeleteField( int iField )
406 {
407 if( !IsUpdatable() || !IngestAll() )
408 return OGRERR_FAILURE;
409 return OGRMemLayer::DeleteField(iField);
410 }
411
412 /************************************************************************/
413 /* ReorderFields() */
414 /************************************************************************/
415
ReorderFields(int * panMap)416 OGRErr OGRGeoJSONLayer::ReorderFields( int* panMap )
417 {
418 if( !IsUpdatable() || !IngestAll() )
419 return OGRERR_FAILURE;
420 return OGRMemLayer::ReorderFields(panMap);
421 }
422
423 /************************************************************************/
424 /* AlterFieldDefn() */
425 /************************************************************************/
426
AlterFieldDefn(int iField,OGRFieldDefn * poNewFieldDefn,int nFlagsIn)427 OGRErr OGRGeoJSONLayer::AlterFieldDefn( int iField,
428 OGRFieldDefn* poNewFieldDefn,
429 int nFlagsIn )
430 {
431 if( !IsUpdatable() || !IngestAll() )
432 return OGRERR_FAILURE;
433 return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
434 }
435
436 /************************************************************************/
437 /* CreateGeomField() */
438 /************************************************************************/
439
CreateGeomField(OGRGeomFieldDefn * poGeomField,int bApproxOK)440 OGRErr OGRGeoJSONLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
441 int bApproxOK )
442 {
443 if( !IsUpdatable() || !IngestAll() )
444 return OGRERR_FAILURE;
445 return OGRMemLayer::CreateGeomField(poGeomField, bApproxOK);
446 }
447
448 /************************************************************************/
449 /* TestCapability() */
450 /************************************************************************/
451
TestCapability(const char * pszCap)452 int OGRGeoJSONLayer::TestCapability( const char * pszCap )
453
454 {
455 if( EQUAL(pszCap, OLCCurveGeometries) )
456 return FALSE;
457 else if( EQUAL(pszCap, OLCStringsAsUTF8) )
458 return TRUE;
459 return OGRMemLayer::TestCapability(pszCap);
460 }
461
462 /************************************************************************/
463 /* SyncToDisk() */
464 /************************************************************************/
465
SyncToDisk()466 OGRErr OGRGeoJSONLayer::SyncToDisk()
467 {
468 TerminateAppendSession();
469
470 poDS_->FlushCache();
471 return OGRERR_NONE;
472 }
473
474 /************************************************************************/
475 /* AddFeature */
476 /************************************************************************/
477
AddFeature(OGRFeature * poFeature)478 void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
479 {
480 GIntBig nFID = poFeature->GetFID();
481
482 // Detect potential FID duplicates and make sure they are eventually
483 // unique.
484 if( -1 == nFID )
485 {
486 nFID = GetFeatureCount(FALSE);
487 OGRFeature* poTryFeature = nullptr;
488 while( (poTryFeature = GetFeature(nFID) ) != nullptr )
489 {
490 nFID++;
491 delete poTryFeature;
492 }
493 }
494 else
495 {
496 OGRFeature* poTryFeature = nullptr;
497 if( (poTryFeature = GetFeature(nFID) ) != nullptr )
498 {
499 if( !bOriginalIdModified_ )
500 {
501 CPLError(
502 CE_Warning, CPLE_AppDefined,
503 "Several features with id = " CPL_FRMT_GIB " have been "
504 "found. Altering it to be unique. This warning will not "
505 "be emitted for this layer",
506 nFID );
507 bOriginalIdModified_ = true;
508 }
509 delete poTryFeature;
510 nFID = GetFeatureCount(FALSE);
511 while( (poTryFeature = GetFeature(nFID) ) != nullptr )
512 {
513 nFID++;
514 delete poTryFeature;
515 }
516 }
517 }
518 poFeature->SetFID( nFID );
519
520 if( !CPL_INT64_FITS_ON_INT32(nFID) )
521 SetMetadataItem(OLMD_FID64, "YES");
522
523 SetUpdatable( true ); // Temporary toggle on updatable flag.
524 CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
525 SetUpdatable( poDS_->IsUpdatable() );
526 SetUpdated( false );
527 }
528
529 /************************************************************************/
530 /* DetectGeometryType */
531 /************************************************************************/
532
DetectGeometryType()533 void OGRGeoJSONLayer::DetectGeometryType()
534 {
535 if( GetLayerDefn()->GetGeomType() != wkbUnknown )
536 return;
537
538 ResetReading();
539 bool bFirstGeometry = true;
540 OGRwkbGeometryType eLayerGeomType = wkbUnknown;
541 OGRFeature* poFeature = nullptr;
542 while( (poFeature = GetNextFeature()) != nullptr )
543 {
544 OGRGeometry* poGeometry = poFeature->GetGeometryRef();
545 if( nullptr != poGeometry )
546 {
547 OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
548 if( !OGRGeoJSONUpdateLayerGeomType(
549 this, bFirstGeometry, eGeomType, eLayerGeomType) )
550 {
551 delete poFeature;
552 break;
553 }
554 }
555 delete poFeature;
556 }
557
558 ResetReading();
559 }
560