OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDS, const char* pszName, const char* pszBaseURL, json_object* poObjCount10) { this->poDS = poDS; osBaseURL = pszBaseURL; SetDescription(pszName); poFeatureDefn = new OGRFeatureDefn(pszName); poFeatureDefn->SetGeomType(wkbMultiPolygon); for(int i = 0; i < (int)sizeof(apsAttrs) / (int)sizeof(apsAttrs[0]); i++) { OGRFieldDefn oField(apsAttrs[i].pszName, apsAttrs[i].eType); poFeatureDefn->AddFieldDefn(&oField); } poFeatureDefn->Reference(); poSRS = new OGRSpatialReference(SRS_WKT_WGS84); poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); bEOF = FALSE; nFeatureCount = -1; nNextFID = 1; poGeoJSONDS = NULL; poGeoJSONLayer = NULL; poMainFilter = NULL; nPageSize = atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "1000")); bStillInFirstPage = FALSE; bAcquiredAscending = -1; bFilterMustBeClientSideEvaluated = FALSE; ResetReading(); if( poObjCount10 != NULL ) { json_object* poCount = json_object_object_get(poObjCount10, "count"); if( poCount != NULL ) nFeatureCount = MAX(0, json_object_get_int64(poCount)); OGRGeoJSONDataSource* poTmpDS = new OGRGeoJSONDataSource(); OGRGeoJSONReader oReader; oReader.SetFlattenNestedAttributes(true, '.'); oReader.ReadLayer( poTmpDS, "layer", poObjCount10 ); OGRLayer* poTmpLayer = poTmpDS->GetLayer(0); if( poTmpLayer ) { OGRFeatureDefn* poTmpFDefn = poTmpLayer->GetLayerDefn(); std::vector<CPLString> aosNewFields; for(int i=0;i<poTmpFDefn->GetFieldCount();i++) { if( poFeatureDefn->GetFieldIndex(poTmpFDefn->GetFieldDefn(i)->GetNameRef()) < 0 ) aosNewFields.push_back(poTmpFDefn->GetFieldDefn(i)->GetNameRef()); } std::sort(aosNewFields.begin(), aosNewFields.end(), OGRPLScenesLayerFieldNameComparator); for(int i=0;i<(int)aosNewFields.size();i++) { OGRFieldDefn oField(poTmpFDefn->GetFieldDefn(poTmpFDefn->GetFieldIndex(aosNewFields[i]))); poFeatureDefn->AddFieldDefn(&oField); } } delete poTmpDS; } }
GIntBig OGRPLScenesLayer::GetFeatureCount(int bForce) { if( nFeatureCount < 0 ) { CPLString osURL(BuildURL(1)); if( bFilterMustBeClientSideEvaluated ) { nFeatureCount = OGRLayer::GetFeatureCount(bForce); } else if( osURL.find('?') == std::string::npos ) { /* Case of a "id = XXXXX" filter: we get directly a Feature, */ /* not a FeatureCollection */ GetNextPage(); } else { nFeatureCount = 0; json_object* poObj = poDS->RunRequest(osURL); if( poObj != NULL ) { json_object* poCount = json_object_object_get(poObj, "count"); if( poCount != NULL ) nFeatureCount = MAX(0, json_object_get_int64(poCount)); // Small optimization, if the feature count is actually 1 // then we can fetch it as the full layer if( nFeatureCount == 1 ) { delete poGeoJSONDS; // Parse the Feature/FeatureCollection with the GeoJSON reader poGeoJSONDS = new OGRGeoJSONDataSource(); OGRGeoJSONReader oReader; oReader.SetFlattenNestedAttributes(true, '.'); oReader.ReadLayer( poGeoJSONDS, "layer", poObj); poGeoJSONLayer = poGeoJSONDS->GetLayer(0); osNextURL = ""; } json_object_put(poObj); } } } return nFeatureCount; }
int OGRPLScenesLayer::GetNextPage() { delete poGeoJSONDS; poGeoJSONLayer = NULL; poGeoJSONDS = NULL; if( osRequestURL.size() == 0 ) { bEOF = TRUE; if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 ) nFeatureCount = 0; return FALSE; } // In the case of a "id = 'foo'" filter, a non existing resource // will cause a 404 error, which we want to be silent int bQuiet404Error = ( osRequestURL.find('?') == std::string::npos ); json_object* poObj = poDS->RunRequest(osRequestURL, bQuiet404Error); if( poObj == NULL ) { bEOF = TRUE; if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 ) nFeatureCount = 0; return FALSE; } if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 ) { json_object* poType = json_object_object_get(poObj, "type"); if( poType && json_object_get_type(poType) == json_type_string && strcmp(json_object_get_string(poType), "Feature") == 0 ) { nFeatureCount = 1; } else { json_object* poCount = json_object_object_get(poObj, "count"); if( poCount == NULL ) { json_object_put(poObj); bEOF = TRUE; nFeatureCount = 0; return FALSE; } nFeatureCount = MAX(0, json_object_get_int64(poCount)); } } // Parse the Feature/FeatureCollection with the GeoJSON reader poGeoJSONDS = new OGRGeoJSONDataSource(); OGRGeoJSONReader oReader; oReader.SetFlattenNestedAttributes(true, '.'); oReader.ReadLayer( poGeoJSONDS, "layer", poObj); poGeoJSONLayer = poGeoJSONDS->GetLayer(0); // Get URL of next page osNextURL = ""; if( poGeoJSONLayer ) { json_object* poLinks = json_object_object_get(poObj, "links"); if( poLinks && json_object_get_type(poLinks) == json_type_object ) { json_object* poNext = json_object_object_get(poLinks, "next"); if( poNext && json_object_get_type(poNext) == json_type_string ) { osNextURL = json_object_get_string(poNext); } } } json_object_put(poObj); return poGeoJSONLayer != NULL; }
void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions) { if( NULL == pszGeoData_ ) { CPLError( CE_Failure, CPLE_ObjectNull, "GeoJSON data buffer empty" ); return; } const char* const apszPrefix[] = { "loadGeoJSON(", "jsonp(" }; for(size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ ) { if( strncmp(pszGeoData_, apszPrefix[iP], strlen(apszPrefix[iP])) == 0 ) { size_t nDataLen = strlen(pszGeoData_); memmove( pszGeoData_, pszGeoData_ + strlen(apszPrefix[iP]), nDataLen - strlen(apszPrefix[iP]) ); size_t i = nDataLen - strlen(apszPrefix[iP]); pszGeoData_[i] = '\0'; while( i > 0 && pszGeoData_[i] != ')' ) { i --; } pszGeoData_[i] = '\0'; } } if ( !GeoJSONIsObject( pszGeoData_) ) { CPLDebug( "GeoJSON", "No valid GeoJSON data found in source '%s'", pszName_ ); return; } OGRErr err = OGRERR_NONE; /* -------------------------------------------------------------------- */ /* Is it ESRI Feature Service data ? */ /* -------------------------------------------------------------------- */ if ( strstr(pszGeoData_, "esriGeometry") || strstr(pszGeoData_, "esriFieldType") ) { OGRESRIJSONReader reader; err = reader.Parse( pszGeoData_ ); if( OGRERR_NONE == err ) { json_object* poObj = reader.GetJSonObject(); if( poObj && json_object_get_type(poObj) == json_type_object ) { json_object* poExceededTransferLimit = json_object_object_get(poObj, "exceededTransferLimit"); if( poExceededTransferLimit && json_object_get_type(poExceededTransferLimit) == json_type_boolean ) bOtherPages_ = json_object_get_boolean(poExceededTransferLimit); } reader.ReadLayers( this ); } return; } /* -------------------------------------------------------------------- */ /* Is it TopoJSON data ? */ /* -------------------------------------------------------------------- */ if ( strstr(pszGeoData_, "\"type\"") && strstr(pszGeoData_, "\"Topology\"") ) { OGRTopoJSONReader reader; err = reader.Parse( pszGeoData_ ); if( OGRERR_NONE == err ) { reader.ReadLayers( this ); } return; } /* -------------------------------------------------------------------- */ /* Configure GeoJSON format translator. */ /* -------------------------------------------------------------------- */ OGRGeoJSONReader reader; if( eGeometryAsCollection == flTransGeom_ ) { reader.SetPreserveGeometryType( false ); CPLDebug( "GeoJSON", "Geometry as OGRGeometryCollection type." ); } if( eAtributesSkip == flTransAttrs_ ) { reader.SetSkipAttributes( true ); CPLDebug( "GeoJSON", "Skip all attributes." ); } reader.SetFlattenNestedAttributes( (bool)CSLFetchBoolean(papszOpenOptions, "FLATTEN_NESTED_ATTRIBUTES", FALSE), CSLFetchNameValueDef(papszOpenOptions, "NESTED_ATTRIBUTE_SEPARATOR", "_")[0]); /* -------------------------------------------------------------------- */ /* Parse GeoJSON and build valid OGRLayer instance. */ /* -------------------------------------------------------------------- */ err = reader.Parse( pszGeoData_ ); if( OGRERR_NONE == err ) { json_object* poObj = reader.GetJSonObject(); if( poObj && json_object_get_type(poObj) == json_type_object ) { json_object* poProperties = json_object_object_get(poObj, "properties"); if( poProperties && json_object_get_type(poProperties) == json_type_object ) { json_object* poExceededTransferLimit = json_object_object_get(poProperties, "exceededTransferLimit"); if( poExceededTransferLimit && json_object_get_type(poExceededTransferLimit) == json_type_boolean ) bOtherPages_ = json_object_get_boolean(poExceededTransferLimit); } } reader.ReadLayers( this ); } return; }