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