EVOLUTION-MANAGER
Edit File: ogrelasticlayer.cpp
/****************************************************************************** * $Id: ogrelasticlayer.cpp 27729 2014-09-24 00:40:16Z goatbar $ * * Project: ElasticSearch Translator * Purpose: * Author: * ****************************************************************************** * Copyright (c) 2011, Adam Estrada * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "ogr_elastic.h" #include "cpl_conv.h" #include "cpl_minixml.h" #include "ogr_api.h" #include "ogr_p.h" #include <json.h> // JSON-C CPL_CVSID("$Id: ogrelasticlayer.cpp 27729 2014-09-24 00:40:16Z goatbar $"); /************************************************************************/ /* OGRElasticLayer() */ /************************************************************************/ OGRElasticLayer::OGRElasticLayer(CPL_UNUSED const char* pszFilename, const char* pszLayerName, OGRElasticDataSource* poDS, OGRSpatialReference *poSRSIn, CPL_UNUSED int bWriteMode) { this->pszLayerName = CPLStrdup(pszLayerName); this->poDS = poDS; this->pAttributes = NULL; // If we are overwriting, then delete the current index if it exists if (poDS->bOverwrite) { poDS->DeleteIndex(CPLSPrintf("%s/%s", poDS->GetName(), pszLayerName)); } // Create the index poDS->UploadFile(CPLSPrintf("%s/%s", poDS->GetName(), pszLayerName), ""); // If we have a user specified mapping, then go ahead and update it now if (poDS->pszMapping != NULL) { poDS->UploadFile(CPLSPrintf("%s/%s/FeatureCollection/_mapping", poDS->GetName(), pszLayerName), poDS->pszMapping); } poFeatureDefn = new OGRFeatureDefn(pszLayerName); poFeatureDefn->Reference(); poSRS = poSRSIn; if (poSRS) poSRS->Reference(); poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); ResetReading(); return; } /************************************************************************/ /* ~OGRElasticLayer() */ /************************************************************************/ OGRElasticLayer::~OGRElasticLayer() { PushIndex(); CPLFree(pszLayerName); poFeatureDefn->Release(); if (poSRS != NULL) poSRS->Release(); } /************************************************************************/ /* GetLayerDefn() */ /************************************************************************/ OGRFeatureDefn * OGRElasticLayer::GetLayerDefn() { return poFeatureDefn; } /************************************************************************/ /* ResetReading() */ /************************************************************************/ void OGRElasticLayer::ResetReading() { return; } /************************************************************************/ /* GetNextFeature() */ /************************************************************************/ OGRFeature *OGRElasticLayer::GetNextFeature() { CPLError(CE_Failure, CPLE_NotSupported, "Cannot read features when writing a Elastic file"); return NULL; } /************************************************************************/ /* AppendGroup() */ /************************************************************************/ json_object *AppendGroup(json_object *parent, const CPLString &name) { json_object *obj = json_object_new_object(); json_object *properties = json_object_new_object(); json_object_object_add(parent, name, obj); json_object_object_add(obj, "properties", properties); return properties; } /************************************************************************/ /* AddPropertyMap() */ /************************************************************************/ json_object *AddPropertyMap(const CPLString &type, const CPLString &format = "") { json_object *obj = json_object_new_object(); json_object_object_add(obj, "store", json_object_new_string("yes")); json_object_object_add(obj, "type", json_object_new_string(type.c_str())); if (!format.empty()) { json_object_object_add(obj, "format", json_object_new_string(format.c_str())); } return obj; } /************************************************************************/ /* BuildMap() */ /************************************************************************/ CPLString OGRElasticLayer::BuildMap() { json_object *map = json_object_new_object(); json_object *properties = json_object_new_object(); json_object *Feature = AppendGroup(map, "FeatureCollection"); json_object_object_add(Feature, "type", AddPropertyMap("string")); json_object_object_add(Feature, "properties", properties); if (pAttributes) json_object_object_add(properties, "properties", (json_object *) pAttributes); json_object *geometry = AppendGroup(Feature, "geometry"); json_object_object_add(geometry, "type", AddPropertyMap("string")); json_object_object_add(geometry, "coordinates", AddPropertyMap("geo_point")); CPLString jsonMap(json_object_to_json_string(map)); json_object_put(map); // The attribute's were freed from the deletion of the map object // because we added it as a child of one of the map object attributes if (pAttributes) { pAttributes = NULL; } return jsonMap; } /************************************************************************/ /* CreateFeature() */ /************************************************************************/ OGRErr OGRElasticLayer::CreateFeature(OGRFeature *poFeature) { // Check to see if the user has elected to only write out the mapping file // This method will only write out one layer from the vector file in cases where there are multiple layers if (poDS->pszWriteMap != NULL) { if (pAttributes) { CPLString map = BuildMap(); // Write the map to a file FILE *f = fopen(poDS->pszWriteMap, "wb"); if (f) { fwrite(map.c_str(), 1, map.length(), f); fclose(f); } } return OGRERR_NONE; } // Check to see if we have any fields to upload to this index if (poDS->pszMapping == NULL && pAttributes) { poDS->UploadFile(CPLSPrintf("%s/%s/FeatureCollection/_mapping", poDS->GetName(), pszLayerName), BuildMap()); } // Get the center point of the geometry OGREnvelope env; if (!poFeature->GetGeometryRef()) { return OGRERR_FAILURE; } poFeature->GetGeometryRef()->getEnvelope(&env); json_object *fieldObject = json_object_new_object(); json_object *geometry = json_object_new_object(); json_object *coordinates = json_object_new_array(); json_object *properties = json_object_new_object(); json_object_object_add(fieldObject, "geometry", geometry); json_object_object_add(geometry, "type", json_object_new_string("POINT")); json_object_object_add(geometry, "coordinates", coordinates); json_object_array_add(coordinates, json_object_new_double((env.MaxX + env.MinX)*0.5)); json_object_array_add(coordinates, json_object_new_double((env.MaxY + env.MinY)*0.5)); json_object_object_add(fieldObject, "type", json_object_new_string("Feature")); json_object_object_add(fieldObject, "properties", properties); // For every field that int fieldCount = poFeatureDefn->GetFieldCount(); for (int i = 0; i < fieldCount; i++) { if(!poFeature->IsFieldSet( i ) ) { continue; } switch (poFeatureDefn->GetFieldDefn(i)->GetType()) { case OFTInteger: json_object_object_add(properties, poFeatureDefn->GetFieldDefn(i)->GetNameRef(), json_object_new_int(poFeature->GetFieldAsInteger(i))); break; case OFTReal: json_object_object_add(properties, poFeatureDefn->GetFieldDefn(i)->GetNameRef(), json_object_new_double(poFeature->GetFieldAsDouble(i))); break; default: { CPLString tmp = poFeature->GetFieldAsString(i); json_object_object_add(properties, poFeatureDefn->GetFieldDefn(i)->GetNameRef(), json_object_new_string(tmp)); } } } // Build the field string CPLString fields(json_object_to_json_string(fieldObject)); json_object_put(fieldObject); // Check to see if we're using bulk uploading if (poDS->nBulkUpload > 0) { sIndex += CPLSPrintf("{\"index\" :{\"_index\":\"%s\", \"_type\":\"FeatureCollection\"}}\n", pszLayerName) + fields + "\n\n"; // Only push the data if we are over our bulk upload limit if ((int) sIndex.length() > poDS->nBulkUpload) { PushIndex(); } } else { // Fall back to using single item upload for every feature poDS->UploadFile(CPLSPrintf("%s/%s/FeatureCollection/", poDS->GetName(), pszLayerName), fields); } return OGRERR_NONE; } /************************************************************************/ /* PushIndex() */ /************************************************************************/ void OGRElasticLayer::PushIndex() { if (sIndex.empty()) { return; } poDS->UploadFile(CPLSPrintf("%s/_bulk", poDS->GetName()), sIndex); sIndex.clear(); } /************************************************************************/ /* CreateField() */ /************************************************************************/ OGRErr OGRElasticLayer::CreateField(OGRFieldDefn *poFieldDefn, CPL_UNUSED int bApproxOK) { if (!pAttributes) { pAttributes = json_object_new_object(); } switch (poFieldDefn->GetType()) { case OFTInteger: json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("integer")); break; case OFTReal: json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("float")); break; case OFTString: json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("string")); break; case OFTDateTime: case OFTDate: json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("date", "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd")); break; default: // These types are mapped as strings and may not be correct /* OFTTime: OFTIntegerList = 1, OFTRealList = 3, OFTStringList = 5, OFTWideString = 6, OFTWideStringList = 7, OFTBinary = 8, OFTMaxType = 11 */ json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("string")); } poFeatureDefn->AddFieldDefn(poFieldDefn); return OGRERR_NONE; } /************************************************************************/ /* TestCapability() */ /************************************************************************/ int OGRElasticLayer::TestCapability(const char * pszCap) { if (EQUAL(pszCap, OLCFastFeatureCount)) return FALSE; else if (EQUAL(pszCap, OLCStringsAsUTF8)) return TRUE; else if (EQUAL(pszCap, OLCSequentialWrite)) return TRUE; else return FALSE; } /************************************************************************/ /* GetFeatureCount() */ /************************************************************************/ int OGRElasticLayer::GetFeatureCount(CPL_UNUSED int bForce) { CPLError(CE_Failure, CPLE_NotSupported, "Cannot read features when writing a Elastic file"); return 0; }