LCOV - code coverage report
Current view: top level - gnm/gnm_frmts/file - gnmfilenetwork.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 200 318 62.9 %
Date: 2025-01-18 12:42:00 Functions: 20 22 90.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
       4             :  * Purpose:  GNM file based generic driver.
       5             :  * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
       6             :  *           Dmitry Baryshnikov, polimax@mail.ru
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2014, Mikhail Gusev
      10             :  * Copyright (c) 2014-2015, NextGIS <info@nextgis.com>
      11             :  *
      12             :  * Permission is hereby granted, free of charge, to any person obtaining a
      13             :  * copy of this software and associated documentation files (the "Software"),
      14             :  * to deal in the Software without restriction, including without limitation
      15             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16             :  * and/or sell copies of the Software, and to permit persons to whom the
      17             :  * Software is furnished to do so, subject to the following conditions:
      18             :  *
      19             :  * The above copyright notice and this permission notice shall be included
      20             :  * in all copies or substantial portions of the Software.
      21             :  *
      22             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28             :  * DEALINGS IN THE SOFTWARE.
      29             :  ****************************************************************************/
      30             : 
      31             : #include "gnmfile.h"
      32             : #include "gnm_priv.h"
      33             : 
      34          16 : GNMFileNetwork::GNMFileNetwork() : GNMGenericNetwork()
      35             : {
      36          16 :     m_pMetadataDS = nullptr;
      37          16 :     m_pGraphDS = nullptr;
      38          16 :     m_pFeaturesDS = nullptr;
      39          16 : }
      40             : 
      41          31 : GNMFileNetwork::~GNMFileNetwork()
      42             : {
      43          16 :     FlushCache(true);
      44             : 
      45          21 :     for (std::map<OGRLayer *, GDALDataset *>::iterator it =
      46          16 :              m_mpLayerDatasetMap.begin();
      47          58 :          it != m_mpLayerDatasetMap.end(); ++it)
      48             :     {
      49          21 :         GDALClose(it->second);
      50             :     }
      51             : 
      52          16 :     m_mpLayerDatasetMap.clear();
      53             : 
      54          16 :     GDALClose(m_pGraphDS);
      55          16 :     GDALClose(m_pFeaturesDS);
      56          16 :     GDALClose(m_pMetadataDS);
      57          31 : }
      58             : 
      59          14 : CPLErr GNMFileNetwork::Open(GDALOpenInfo *poOpenInfo)
      60             : {
      61          14 :     m_soNetworkFullName = poOpenInfo->pszFilename;
      62          14 :     char **papszFiles = VSIReadDir(m_soNetworkFullName);
      63          14 :     if (CSLCount(papszFiles) == 0)
      64             :     {
      65           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
      66             :                  m_soNetworkFullName.c_str());
      67           0 :         return CE_Failure;
      68             :     }
      69             : 
      70             :     // search for metadata file
      71          28 :     CPLString soMetadatafile;
      72          39 :     for (int i = 0; papszFiles[i] != nullptr; i++)
      73             :     {
      74          39 :         if (EQUAL(papszFiles[i], ".") || EQUAL(papszFiles[i], ".."))
      75           0 :             continue;
      76             : 
      77          39 :         if (EQUAL(CPLGetBasenameSafe(papszFiles[i]).c_str(), GNM_SYSLAYER_META))
      78             :         {
      79          14 :             soMetadatafile = CPLFormFilenameSafe(m_soNetworkFullName,
      80          28 :                                                  papszFiles[i], nullptr);
      81          14 :             break;
      82             :         }
      83             :     }
      84             : 
      85          14 :     CSLDestroy(papszFiles);
      86             : 
      87          14 :     m_pMetadataDS = (GDALDataset *)GDALOpenEx(soMetadatafile,
      88             :                                               GDAL_OF_VECTOR | GDAL_OF_UPDATE,
      89             :                                               nullptr, nullptr, nullptr);
      90          14 :     if (nullptr == m_pMetadataDS)
      91             :     {
      92           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
      93             :                  m_soNetworkFullName.c_str());
      94           0 :         return CE_Failure;
      95             :     }
      96             : 
      97          14 :     if (LoadMetadataLayer(m_pMetadataDS) != CE_None)
      98             :     {
      99           0 :         return CE_Failure;
     100             :     }
     101             : 
     102          14 :     m_poLayerDriver = m_pMetadataDS->GetDriver();
     103          28 :     const CPLString osExt = CPLGetExtensionSafe(soMetadatafile);
     104             : 
     105             :     const CPLString soGraphfile =
     106          28 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SYSLAYER_GRAPH, osExt);
     107          14 :     m_pGraphDS =
     108          14 :         (GDALDataset *)GDALOpenEx(soGraphfile, GDAL_OF_VECTOR | GDAL_OF_UPDATE,
     109             :                                   nullptr, nullptr, nullptr);
     110          14 :     if (nullptr == m_pGraphDS)
     111             :     {
     112           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
     113             :                  m_soNetworkFullName.c_str());
     114           0 :         return CE_Failure;
     115             :     }
     116             : 
     117          14 :     if (LoadGraphLayer(m_pGraphDS) != CE_None)
     118             :     {
     119           0 :         return CE_Failure;
     120             :     }
     121             : 
     122             :     const CPLString soFeaturesfile =
     123          28 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SYSLAYER_FEATURES, osExt);
     124          14 :     m_pFeaturesDS = (GDALDataset *)GDALOpenEx(soFeaturesfile,
     125             :                                               GDAL_OF_VECTOR | GDAL_OF_UPDATE,
     126             :                                               nullptr, nullptr, nullptr);
     127          14 :     if (nullptr == m_pFeaturesDS)
     128             :     {
     129           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
     130             :                  m_soNetworkFullName.c_str());
     131           0 :         return CE_Failure;
     132             :     }
     133             : 
     134          14 :     if (LoadFeaturesLayer(m_pFeaturesDS) != CE_None)
     135             :     {
     136           0 :         return CE_Failure;
     137             :     }
     138             : 
     139          14 :     return CE_None;
     140             : }
     141             : 
     142           2 : int GNMFileNetwork::CheckNetworkExist(const char *pszFilename,
     143             :                                       char **papszOptions)
     144             : {
     145             :     // check if path exist
     146             :     // if path exist check if network already present and OVERWRITE option
     147             :     // else create the path
     148             : 
     149           2 :     const bool bOverwrite = CPLFetchBool(papszOptions, "OVERWRITE", false);
     150             : 
     151           2 :     if (m_soName.empty())
     152             :     {
     153             :         const char *pszNetworkName =
     154           0 :             CSLFetchNameValue(papszOptions, GNM_MD_NAME);
     155             : 
     156           0 :         if (nullptr != pszNetworkName)
     157             :         {
     158           0 :             m_soName = pszNetworkName;
     159             :         }
     160             :     }
     161             : 
     162           2 :     if (FormPath(pszFilename, papszOptions) != CE_None)
     163             :     {
     164           0 :         return TRUE;
     165             :     }
     166             : 
     167           2 :     if (CPLCheckForFile((char *)m_soNetworkFullName.c_str(), nullptr))
     168             :     {
     169           0 :         char **papszFiles = VSIReadDir(m_soNetworkFullName);
     170           0 :         if (CSLCount(papszFiles) == 0)
     171             :         {
     172           0 :             return FALSE;
     173             :         }
     174             : 
     175             :         // search for base GNM files
     176           0 :         for (int i = 0; papszFiles[i] != nullptr; i++)
     177             :         {
     178           0 :             if (EQUAL(papszFiles[i], ".") || EQUAL(papszFiles[i], ".."))
     179           0 :                 continue;
     180             : 
     181           0 :             const CPLString osBasename = CPLGetBasenameSafe(papszFiles[i]);
     182           0 :             if (EQUAL(osBasename, GNM_SYSLAYER_META) ||
     183           0 :                 EQUAL(osBasename, GNM_SYSLAYER_GRAPH) ||
     184           0 :                 EQUAL(osBasename, GNM_SYSLAYER_FEATURES) ||
     185           0 :                 EQUAL(papszFiles[i], GNM_SRSFILENAME))
     186             :             {
     187           0 :                 if (bOverwrite)
     188             :                 {
     189             :                     const std::string osDeleteFile = CPLFormFilenameSafe(
     190           0 :                         m_soNetworkFullName, papszFiles[i], nullptr);
     191           0 :                     CPLDebug("GNM", "Delete file: %s", osDeleteFile.c_str());
     192           0 :                     if (VSIUnlink(osDeleteFile.c_str()) != 0)
     193             :                     {
     194           0 :                         return TRUE;
     195             :                     }
     196             :                 }
     197             :                 else
     198             :                 {
     199           0 :                     return TRUE;
     200             :                 }
     201             :             }
     202             :         }
     203           0 :         CSLDestroy(papszFiles);
     204             :     }
     205             :     else
     206             :     {
     207           2 :         if (VSIMkdir(m_soNetworkFullName, 0755) != 0)
     208             :         {
     209           0 :             return TRUE;
     210             :         }
     211             :     }
     212             : 
     213           2 :     return FALSE;
     214             : }
     215             : 
     216           2 : CPLErr GNMFileNetwork::Delete()
     217             : {
     218           2 :     CPLErr eResult = GNMGenericNetwork::Delete();
     219           2 :     if (eResult != CE_None)
     220           0 :         return eResult;
     221             : 
     222             :     // check if folder empty
     223           2 :     char **papszFiles = VSIReadDir(m_soNetworkFullName);
     224           2 :     bool bIsEmpty = true;
     225           6 :     for (int i = 0; papszFiles[i] != nullptr; ++i)
     226             :     {
     227           4 :         if (!(EQUAL(papszFiles[i], "..") || EQUAL(papszFiles[i], ".")))
     228             :         {
     229           0 :             bIsEmpty = false;
     230           0 :             break;
     231             :         }
     232             :     }
     233             : 
     234           2 :     CSLDestroy(papszFiles);
     235             : 
     236           2 :     if (!bIsEmpty)
     237             :     {
     238           0 :         return eResult;
     239             :     }
     240           2 :     return VSIRmdir(m_soNetworkFullName) == 0 ? CE_None : CE_Failure;
     241             : }
     242             : 
     243           2 : CPLErr GNMFileNetwork::CreateMetadataLayerFromFile(const char *pszFilename,
     244             :                                                    int nVersion,
     245             :                                                    char **papszOptions)
     246             : {
     247           2 :     CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
     248           2 :     if (CE_None != eResult)
     249           0 :         return eResult;
     250             : 
     251           2 :     eResult = FormPath(pszFilename, papszOptions);
     252           2 :     if (CE_None != eResult)
     253           0 :         return eResult;
     254             : 
     255           2 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     256             :     const CPLString osDSFileName =
     257           4 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SYSLAYER_META, pszExt);
     258             : 
     259           2 :     m_pMetadataDS =
     260           2 :         m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown, nullptr);
     261           2 :     if (nullptr == m_pMetadataDS)
     262             :     {
     263           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
     264             :                  osDSFileName.c_str());
     265           0 :         return CE_Failure;
     266             :     }
     267             : 
     268           2 :     return GNMGenericNetwork::CreateMetadataLayer(m_pMetadataDS, nVersion, 254);
     269             : }
     270             : 
     271           2 : CPLErr GNMFileNetwork::StoreNetworkSrs()
     272             : {
     273           2 :     if (m_oSRS.IsEmpty())
     274           0 :         return CE_None;
     275             :     const std::string osSrsFileName =
     276           4 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SRSFILENAME, nullptr);
     277           2 :     VSILFILE *fpSrsPrj = VSIFOpenL(osSrsFileName.c_str(), "w");
     278           2 :     if (fpSrsPrj != nullptr)
     279             :     {
     280           2 :         char *pszWKT = nullptr;
     281           2 :         m_oSRS.exportToWkt(&pszWKT);
     282           2 :         if (pszWKT && VSIFWriteL(pszWKT, (int)strlen(pszWKT), 1, fpSrsPrj) != 1)
     283             :         {
     284           0 :             CPLFree(pszWKT);
     285           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     286             :                      "Write SRS failed, disk full?");
     287           0 :             VSIFCloseL(fpSrsPrj);
     288           0 :             return CE_Failure;
     289             :         }
     290           2 :         CPLFree(pszWKT);
     291           2 :         VSIFCloseL(fpSrsPrj);
     292             :     }
     293           2 :     return CE_None;
     294             : }
     295             : 
     296           0 : CPLErr GNMFileNetwork::LoadNetworkSrs()
     297             : {
     298             :     const std::string osSrsFileName =
     299           0 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SRSFILENAME, nullptr);
     300           0 :     char **papszLines = CSLLoad(osSrsFileName.c_str());
     301           0 :     if (nullptr == papszLines)
     302             :     {
     303           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
     304             :                  GNM_SYSLAYER_META);
     305           0 :         return CE_Failure;
     306             :     }
     307             : 
     308           0 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     309           0 :     m_oSRS.importFromWkt(papszLines[0]);
     310             : 
     311           0 :     CSLDestroy(papszLines);
     312             : 
     313           0 :     return CE_None;
     314             : }
     315             : 
     316           2 : CPLErr GNMFileNetwork::DeleteMetadataLayer()
     317             : {
     318           2 :     if (nullptr != m_pMetadataDS)
     319             :     {
     320             :         const std::string osSrsFileName =
     321           2 :             CPLFormFilenameSafe(m_soNetworkFullName, GNM_SRSFILENAME, nullptr);
     322           2 :         VSIUnlink(
     323             :             osSrsFileName
     324             :                 .c_str());  // just try to delete as file may not be existed
     325           2 :         return m_pMetadataDS->DeleteLayer(0) == OGRERR_NONE ? CE_None
     326           2 :                                                             : CE_Failure;
     327             :     }
     328           0 :     return CE_Failure;
     329             : }
     330             : 
     331           2 : CPLErr GNMFileNetwork::CreateGraphLayerFromFile(const char *pszFilename,
     332             :                                                 char **papszOptions)
     333             : {
     334           2 :     CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
     335           2 :     if (CE_None != eResult)
     336           0 :         return eResult;
     337             : 
     338           2 :     eResult = FormPath(pszFilename, papszOptions);
     339           2 :     if (CE_None != eResult)
     340           0 :         return eResult;
     341             : 
     342           2 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     343             :     const CPLString osDSFileName =
     344           4 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SYSLAYER_GRAPH, pszExt);
     345             : 
     346           2 :     m_pGraphDS =
     347           2 :         m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown, nullptr);
     348             : 
     349           2 :     if (m_pGraphDS == nullptr)
     350             :     {
     351           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
     352             :                  osDSFileName.c_str());
     353           0 :         return CE_Failure;
     354             :     }
     355             : 
     356           2 :     return GNMGenericNetwork::CreateGraphLayer(m_pGraphDS);
     357             : }
     358             : 
     359           2 : CPLErr GNMFileNetwork::DeleteGraphLayer()
     360             : {
     361           2 :     if (nullptr != m_pGraphDS)
     362             :     {
     363           2 :         return m_pGraphDS->DeleteLayer(0) == OGRERR_NONE ? CE_None : CE_Failure;
     364             :     }
     365           0 :     return CE_Failure;
     366             : }
     367             : 
     368           2 : CPLErr GNMFileNetwork::CreateFeaturesLayerFromFile(const char *pszFilename,
     369             :                                                    char **papszOptions)
     370             : {
     371           2 :     CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
     372           2 :     if (CE_None != eResult)
     373           0 :         return eResult;
     374             : 
     375           2 :     eResult = FormPath(pszFilename, papszOptions);
     376           2 :     if (CE_None != eResult)
     377           0 :         return eResult;
     378             : 
     379           2 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     380             :     const CPLString osDSFileName =
     381           4 :         CPLFormFilenameSafe(m_soNetworkFullName, GNM_SYSLAYER_FEATURES, pszExt);
     382             : 
     383           2 :     m_pFeaturesDS =
     384           2 :         m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown, nullptr);
     385             : 
     386           2 :     if (m_pFeaturesDS == nullptr)
     387             :     {
     388           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
     389             :                  osDSFileName.c_str());
     390           0 :         return CE_Failure;
     391             :     }
     392             : 
     393           2 :     return GNMGenericNetwork::CreateFeaturesLayer(m_pFeaturesDS);
     394             : }
     395             : 
     396           2 : CPLErr GNMFileNetwork::DeleteFeaturesLayer()
     397             : {
     398           2 :     if (nullptr != m_pFeaturesDS)
     399             :     {
     400           2 :         return m_pFeaturesDS->DeleteLayer(0) == OGRERR_NONE ? CE_None
     401           2 :                                                             : CE_Failure;
     402             :     }
     403           0 :     return CE_Failure;
     404             : }
     405             : 
     406           6 : CPLErr GNMFileNetwork::DeleteNetworkLayers()
     407             : {
     408           6 :     while (GetLayerCount() > 0)
     409             :     {
     410           4 :         OGRErr eErr = DeleteLayer(0);
     411           4 :         if (eErr != OGRERR_NONE)
     412           0 :             return CE_Failure;
     413             :     }
     414           2 :     return CE_None;
     415             : }
     416             : 
     417         673 : CPLErr GNMFileNetwork::LoadNetworkLayer(const char *pszLayername)
     418             : {
     419             :     // check if not loaded
     420         983 :     for (size_t i = 0; i < m_apoLayers.size(); ++i)
     421             :     {
     422         962 :         if (EQUAL(m_apoLayers[i]->GetName(), pszLayername))
     423         652 :             return CE_None;
     424             :     }
     425             : 
     426          21 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     427             : 
     428             :     const CPLString soFile =
     429          42 :         CPLFormFilenameSafe(m_soNetworkFullName, pszLayername, pszExt);
     430          21 :     GDALDataset *poDS = (GDALDataset *)GDALOpenEx(
     431             :         soFile, GDAL_OF_VECTOR | GDAL_OF_UPDATE, nullptr, nullptr, nullptr);
     432          21 :     if (nullptr == poDS)
     433             :     {
     434           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
     435             :                  soFile.c_str());
     436           0 :         return CE_Failure;
     437             :     }
     438             : 
     439          21 :     OGRLayer *poLayer = poDS->GetLayer(0);
     440          21 :     if (nullptr == poLayer)
     441             :     {
     442           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Layer '%s' is not exist",
     443             :                  pszLayername);
     444           0 :         return CE_Failure;
     445             :     }
     446             : 
     447          21 :     CPLDebug("GNM", "Layer '%s' loaded", poLayer->GetName());
     448             : 
     449          21 :     GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
     450          21 :     m_apoLayers.push_back(pGNMLayer);
     451          21 :     m_mpLayerDatasetMap[pGNMLayer] = poDS;
     452             : 
     453          21 :     return CE_None;
     454             : }
     455             : 
     456           2 : bool GNMFileNetwork::CheckStorageDriverSupport(const char *pszDriverName)
     457             : {
     458           2 :     if (EQUAL(pszDriverName, GNM_MD_DEFAULT_FILE_FORMAT))
     459           2 :         return true;
     460             :     // TODO: expand this list with supported OGR direvers
     461           0 :     return false;
     462             : }
     463             : 
     464           8 : CPLErr GNMFileNetwork::FormPath(const char *pszFilename, char **papszOptions)
     465             : {
     466           8 :     if (m_soNetworkFullName.empty())
     467             :     {
     468             :         const char *pszNetworkName =
     469           2 :             CSLFetchNameValue(papszOptions, GNM_MD_NAME);
     470           2 :         if (nullptr == pszNetworkName)
     471             :         {
     472           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     473             :                      "The network name should be present");
     474           0 :             return CE_Failure;
     475             :         }
     476             :         m_soNetworkFullName =
     477           2 :             CPLFormFilenameSafe(pszFilename, pszNetworkName, nullptr);
     478             : 
     479           2 :         CPLDebug("GNM", "Network name: %s", m_soNetworkFullName.c_str());
     480             :     }
     481           8 :     return CE_None;
     482             : }
     483             : 
     484           0 : int GNMFileNetwork::CloseDependentDatasets()
     485             : {
     486           0 :     size_t nCount = m_mpLayerDatasetMap.size();
     487           0 :     for (std::map<OGRLayer *, GDALDataset *>::iterator it =
     488           0 :              m_mpLayerDatasetMap.begin();
     489           0 :          it != m_mpLayerDatasetMap.end(); ++it)
     490             :     {
     491           0 :         GDALClose(it->second);
     492             :     }
     493             : 
     494           0 :     m_mpLayerDatasetMap.clear();
     495             : 
     496           0 :     GNMGenericNetwork::CloseDependentDatasets();
     497             : 
     498           0 :     return nCount > 0 ? TRUE : FALSE;
     499             : }
     500             : 
     501           4 : OGRErr GNMFileNetwork::DeleteLayer(int nIndex)
     502             : {
     503           4 :     OGRLayer *pLayer = GetLayer(nIndex);
     504             : 
     505           4 :     GDALDataset *poDS = m_mpLayerDatasetMap[pLayer];
     506           4 :     if (nullptr == poDS)
     507             :     {
     508           0 :         return OGRERR_FAILURE;
     509             :     }
     510             : 
     511           4 :     CPLDebug("GNM", "Delete network layer '%s'", pLayer->GetName());
     512             : 
     513           4 :     if (poDS->DeleteLayer(0) != OGRERR_NONE)
     514             :     {
     515           0 :         return OGRERR_FAILURE;
     516             :     }
     517             : 
     518           4 :     GDALClose(poDS);
     519             : 
     520             :     // remove pointer from map
     521           4 :     m_mpLayerDatasetMap.erase(pLayer);
     522             : 
     523           4 :     return GNMGenericNetwork::DeleteLayer(nIndex);
     524             : }
     525             : 
     526           4 : OGRLayer *GNMFileNetwork::ICreateLayer(const char *pszName,
     527             :                                        const OGRGeomFieldDefn *poGeomFieldDefn,
     528             :                                        CSLConstList papszOptions)
     529             : {
     530           4 :     if (nullptr == m_poLayerDriver)
     531             :     {
     532           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     533             :                  "The network storage format driver is not defined.");
     534           0 :         return nullptr;
     535             :     }
     536             : 
     537           4 :     const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     538             : 
     539             :     // check if layer with such name exist
     540           6 :     for (int i = 0; i < GetLayerCount(); ++i)
     541             :     {
     542           2 :         OGRLayer *pLayer = GetLayer(i);
     543           2 :         if (nullptr == pLayer)
     544           0 :             continue;
     545           2 :         if (EQUAL(pLayer->GetName(), pszName))
     546             :         {
     547           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     548             :                      "The network layer '%s' already exist.", pszName);
     549           0 :             return nullptr;
     550             :         }
     551             :     }
     552             : 
     553             :     // form path
     554           4 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     555             :     const CPLString soPath =
     556           8 :         CPLFormFilenameSafe(m_soNetworkFullName, pszName, pszExt);
     557             : 
     558             :     GDALDataset *poDS =
     559           4 :         m_poLayerDriver->Create(soPath, 0, 0, 0, GDT_Unknown, papszOptions);
     560           4 :     if (poDS == nullptr)
     561             :     {
     562           0 :         CPLError(CE_Failure, CPLE_FileIO, "Creation of output file failed.");
     563           0 :         return nullptr;
     564             :     }
     565             : 
     566           8 :     OGRSpatialReference oSpaRef(m_oSRS);
     567             : 
     568             :     OGRLayer *poLayer =
     569           4 :         poDS->CreateLayer(pszName, &oSpaRef, eGType, papszOptions);
     570           4 :     if (poLayer == nullptr)
     571             :     {
     572           0 :         CPLError(CE_Failure, CPLE_FileIO, "Layer creation failed.");
     573           0 :         GDALClose(poDS);
     574           0 :         return nullptr;
     575             :     }
     576             : 
     577           8 :     OGRFieldDefn oField(GNM_SYSFIELD_GFID, GNMGFIDInt);
     578           4 :     if (poLayer->CreateField(&oField) != OGRERR_NONE)
     579             :     {
     580           0 :         CPLError(CE_Failure, CPLE_FileIO,
     581             :                  "Creating global identificator field failed.");
     582           0 :         GDALClose(poDS);
     583           0 :         return nullptr;
     584             :     }
     585             : 
     586           8 :     OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
     587           4 :     if (poLayer->CreateField(&oFieldBlock) != OGRERR_NONE)
     588             :     {
     589           0 :         CPLError(CE_Failure, CPLE_FileIO, "Creating is blocking field failed.");
     590           0 :         GDALClose(poDS);
     591           0 :         return nullptr;
     592             :     }
     593             : 
     594           4 :     GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
     595           4 :     m_apoLayers.push_back(pGNMLayer);
     596           4 :     m_mpLayerDatasetMap[pGNMLayer] = poDS;
     597           4 :     return pGNMLayer;
     598             : }
     599             : 
     600           2 : CPLErr GNMFileNetwork::Create(const char *pszFilename, char **papszOptions)
     601             : {
     602             :     // check required options
     603             : 
     604             :     // check name
     605           2 :     const char *pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
     606             : 
     607           2 :     if (nullptr == pszNetworkName)
     608             :     {
     609           0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     610             :                  "The network name should be present");
     611           0 :         return CE_Failure;
     612             :     }
     613             :     else
     614             :     {
     615           2 :         m_soName = pszNetworkName;
     616             :     }
     617             : 
     618             :     const char *pszNetworkDescription =
     619           2 :         CSLFetchNameValue(papszOptions, GNM_MD_DESCR);
     620           2 :     if (nullptr != pszNetworkDescription)
     621           2 :         sDescription = pszNetworkDescription;
     622             : 
     623             :     // check Spatial reference
     624           2 :     const char *pszSRS = CSLFetchNameValue(papszOptions, GNM_MD_SRS);
     625           2 :     if (nullptr == pszSRS)
     626             :     {
     627           0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     628             :                  "The network spatial reference should be present");
     629           0 :         return CE_Failure;
     630             :     }
     631             :     else
     632             :     {
     633           2 :         OGRSpatialReference spatialRef;
     634           2 :         spatialRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     635           2 :         if (spatialRef.SetFromUserInput(pszSRS) != OGRERR_NONE)
     636             :         {
     637           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     638             :                      "The network spatial reference should be present");
     639           0 :             return CE_Failure;
     640             :         }
     641             : 
     642           2 :         m_oSRS = std::move(spatialRef);
     643             :     }
     644             : 
     645           2 :     int nResult = CheckNetworkExist(pszFilename, papszOptions);
     646             : 
     647           2 :     if (TRUE == nResult)
     648             :     {
     649           0 :         CPLError(CE_Failure, CPLE_IllegalArg, "The network already exist");
     650           0 :         return CE_Failure;
     651             :     }
     652             : 
     653             :     // Create the necessary system layers and fields
     654             : 
     655             :     // Create meta layer
     656             : 
     657             :     CPLErr eResult =
     658           2 :         CreateMetadataLayerFromFile(pszFilename, GNM_VERSION_NUM, papszOptions);
     659             : 
     660           2 :     if (CE_None != eResult)
     661             :     {
     662             :         // an error message should come from function
     663           0 :         return CE_Failure;
     664             :     }
     665             : 
     666             :     // Create graph layer
     667             : 
     668           2 :     eResult = CreateGraphLayerFromFile(pszFilename, papszOptions);
     669             : 
     670           2 :     if (CE_None != eResult)
     671             :     {
     672           0 :         DeleteMetadataLayer();
     673           0 :         return CE_Failure;
     674             :     }
     675             : 
     676             :     // Create features layer
     677             : 
     678           2 :     eResult = CreateFeaturesLayerFromFile(pszFilename, papszOptions);
     679             : 
     680           2 :     if (CE_None != eResult)
     681             :     {
     682           0 :         DeleteMetadataLayer();
     683           0 :         DeleteGraphLayer();
     684           0 :         return CE_Failure;
     685             :     }
     686             : 
     687           2 :     return CE_None;
     688             : }

Generated by: LCOV version 1.14