LCOV - code coverage report
Current view: top level - gnm/gnm_frmts/file - gnmfilenetwork.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 199 317 62.8 %
Date: 2024-05-04 12:52:34 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          35 :     for (int i = 0; papszFiles[i] != nullptr; i++)
      73             :     {
      74          35 :         if (EQUAL(papszFiles[i], ".") || EQUAL(papszFiles[i], ".."))
      75           0 :             continue;
      76             : 
      77          35 :         if (EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_META))
      78             :         {
      79             :             soMetadatafile =
      80          14 :                 CPLFormFilename(m_soNetworkFullName, 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 :     CPLString osExt = CPLGetExtension(soMetadatafile);
     104             : 
     105             :     CPLString soGraphfile =
     106          28 :         CPLFormFilename(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             :     CPLString soFeaturesfile =
     123          28 :         CPLFormFilename(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 :             if (EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_META) ||
     182           0 :                 EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_GRAPH) ||
     183           0 :                 EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_FEATURES) ||
     184           0 :                 EQUAL(papszFiles[i], GNM_SRSFILENAME))
     185             :             {
     186           0 :                 if (bOverwrite)
     187             :                 {
     188           0 :                     const char *pszDeleteFile = CPLFormFilename(
     189           0 :                         m_soNetworkFullName, papszFiles[i], nullptr);
     190           0 :                     CPLDebug("GNM", "Delete file: %s", pszDeleteFile);
     191           0 :                     if (VSIUnlink(pszDeleteFile) != 0)
     192             :                     {
     193           0 :                         return TRUE;
     194             :                     }
     195             :                 }
     196             :                 else
     197             :                 {
     198           0 :                     return TRUE;
     199             :                 }
     200             :             }
     201             :         }
     202           0 :         CSLDestroy(papszFiles);
     203             :     }
     204             :     else
     205             :     {
     206           2 :         if (VSIMkdir(m_soNetworkFullName, 0755) != 0)
     207             :         {
     208           0 :             return TRUE;
     209             :         }
     210             :     }
     211             : 
     212           2 :     return FALSE;
     213             : }
     214             : 
     215           2 : CPLErr GNMFileNetwork::Delete()
     216             : {
     217           2 :     CPLErr eResult = GNMGenericNetwork::Delete();
     218           2 :     if (eResult != CE_None)
     219           0 :         return eResult;
     220             : 
     221             :     // check if folder empty
     222           2 :     char **papszFiles = VSIReadDir(m_soNetworkFullName);
     223           2 :     bool bIsEmpty = true;
     224           6 :     for (int i = 0; papszFiles[i] != nullptr; ++i)
     225             :     {
     226           4 :         if (!(EQUAL(papszFiles[i], "..") || EQUAL(papszFiles[i], ".")))
     227             :         {
     228           0 :             bIsEmpty = false;
     229           0 :             break;
     230             :         }
     231             :     }
     232             : 
     233           2 :     CSLDestroy(papszFiles);
     234             : 
     235           2 :     if (!bIsEmpty)
     236             :     {
     237           0 :         return eResult;
     238             :     }
     239           2 :     return VSIRmdir(m_soNetworkFullName) == 0 ? CE_None : CE_Failure;
     240             : }
     241             : 
     242           2 : CPLErr GNMFileNetwork::CreateMetadataLayerFromFile(const char *pszFilename,
     243             :                                                    int nVersion,
     244             :                                                    char **papszOptions)
     245             : {
     246           2 :     CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
     247           2 :     if (CE_None != eResult)
     248           0 :         return eResult;
     249             : 
     250           2 :     eResult = FormPath(pszFilename, papszOptions);
     251           2 :     if (CE_None != eResult)
     252           0 :         return eResult;
     253             : 
     254           2 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     255             :     CPLString osDSFileName =
     256           4 :         CPLFormFilename(m_soNetworkFullName, GNM_SYSLAYER_META, pszExt);
     257             : 
     258           2 :     m_pMetadataDS =
     259           2 :         m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown, nullptr);
     260           2 :     if (nullptr == m_pMetadataDS)
     261             :     {
     262           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
     263             :                  osDSFileName.c_str());
     264           0 :         return CE_Failure;
     265             :     }
     266             : 
     267           2 :     return GNMGenericNetwork::CreateMetadataLayer(m_pMetadataDS, nVersion, 254);
     268             : }
     269             : 
     270           2 : CPLErr GNMFileNetwork::StoreNetworkSrs()
     271             : {
     272           2 :     if (m_oSRS.IsEmpty())
     273           0 :         return CE_None;
     274             :     const char *pszSrsFileName =
     275           2 :         CPLFormFilename(m_soNetworkFullName, GNM_SRSFILENAME, nullptr);
     276           2 :     VSILFILE *fpSrsPrj = VSIFOpenL(pszSrsFileName, "w");
     277           2 :     if (fpSrsPrj != nullptr)
     278             :     {
     279           2 :         char *pszWKT = nullptr;
     280           2 :         m_oSRS.exportToWkt(&pszWKT);
     281           2 :         if (pszWKT && VSIFWriteL(pszWKT, (int)strlen(pszWKT), 1, fpSrsPrj) != 1)
     282             :         {
     283           0 :             CPLFree(pszWKT);
     284           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     285             :                      "Write SRS failed, disk full?");
     286           0 :             VSIFCloseL(fpSrsPrj);
     287           0 :             return CE_Failure;
     288             :         }
     289           2 :         CPLFree(pszWKT);
     290           2 :         VSIFCloseL(fpSrsPrj);
     291             :     }
     292           2 :     return CE_None;
     293             : }
     294             : 
     295           0 : CPLErr GNMFileNetwork::LoadNetworkSrs()
     296             : {
     297             :     const char *pszSrsFileName =
     298           0 :         CPLFormFilename(m_soNetworkFullName, GNM_SRSFILENAME, nullptr);
     299           0 :     char **papszLines = CSLLoad(pszSrsFileName);
     300           0 :     if (nullptr == papszLines)
     301             :     {
     302           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
     303             :                  GNM_SYSLAYER_META);
     304           0 :         return CE_Failure;
     305             :     }
     306             : 
     307           0 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     308           0 :     m_oSRS.importFromWkt(papszLines[0]);
     309             : 
     310           0 :     CSLDestroy(papszLines);
     311             : 
     312           0 :     return CE_None;
     313             : }
     314             : 
     315           2 : CPLErr GNMFileNetwork::DeleteMetadataLayer()
     316             : {
     317           2 :     if (nullptr != m_pMetadataDS)
     318             :     {
     319             :         const char *pszSrsFileName =
     320           2 :             CPLFormFilename(m_soNetworkFullName, GNM_SRSFILENAME, nullptr);
     321           2 :         VSIUnlink(
     322             :             pszSrsFileName);  // just try to delete as file may not be existed
     323           2 :         return m_pMetadataDS->DeleteLayer(0) == OGRERR_NONE ? CE_None
     324           2 :                                                             : CE_Failure;
     325             :     }
     326           0 :     return CE_Failure;
     327             : }
     328             : 
     329           2 : CPLErr GNMFileNetwork::CreateGraphLayerFromFile(const char *pszFilename,
     330             :                                                 char **papszOptions)
     331             : {
     332           2 :     CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
     333           2 :     if (CE_None != eResult)
     334           0 :         return eResult;
     335             : 
     336           2 :     eResult = FormPath(pszFilename, papszOptions);
     337           2 :     if (CE_None != eResult)
     338           0 :         return eResult;
     339             : 
     340           2 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     341             :     CPLString osDSFileName =
     342           4 :         CPLFormFilename(m_soNetworkFullName, GNM_SYSLAYER_GRAPH, pszExt);
     343             : 
     344           2 :     m_pGraphDS =
     345           2 :         m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown, nullptr);
     346             : 
     347           2 :     if (m_pGraphDS == nullptr)
     348             :     {
     349           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
     350             :                  osDSFileName.c_str());
     351           0 :         return CE_Failure;
     352             :     }
     353             : 
     354           2 :     return GNMGenericNetwork::CreateGraphLayer(m_pGraphDS);
     355             : }
     356             : 
     357           2 : CPLErr GNMFileNetwork::DeleteGraphLayer()
     358             : {
     359           2 :     if (nullptr != m_pGraphDS)
     360             :     {
     361           2 :         return m_pGraphDS->DeleteLayer(0) == OGRERR_NONE ? CE_None : CE_Failure;
     362             :     }
     363           0 :     return CE_Failure;
     364             : }
     365             : 
     366           2 : CPLErr GNMFileNetwork::CreateFeaturesLayerFromFile(const char *pszFilename,
     367             :                                                    char **papszOptions)
     368             : {
     369           2 :     CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
     370           2 :     if (CE_None != eResult)
     371           0 :         return eResult;
     372             : 
     373           2 :     eResult = FormPath(pszFilename, papszOptions);
     374           2 :     if (CE_None != eResult)
     375           0 :         return eResult;
     376             : 
     377           2 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     378             :     CPLString osDSFileName =
     379           4 :         CPLFormFilename(m_soNetworkFullName, GNM_SYSLAYER_FEATURES, pszExt);
     380             : 
     381           2 :     m_pFeaturesDS =
     382           2 :         m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown, nullptr);
     383             : 
     384           2 :     if (m_pFeaturesDS == nullptr)
     385             :     {
     386           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
     387             :                  osDSFileName.c_str());
     388           0 :         return CE_Failure;
     389             :     }
     390             : 
     391           2 :     return GNMGenericNetwork::CreateFeaturesLayer(m_pFeaturesDS);
     392             : }
     393             : 
     394           2 : CPLErr GNMFileNetwork::DeleteFeaturesLayer()
     395             : {
     396           2 :     if (nullptr != m_pFeaturesDS)
     397             :     {
     398           2 :         return m_pFeaturesDS->DeleteLayer(0) == OGRERR_NONE ? CE_None
     399           2 :                                                             : CE_Failure;
     400             :     }
     401           0 :     return CE_Failure;
     402             : }
     403             : 
     404           6 : CPLErr GNMFileNetwork::DeleteNetworkLayers()
     405             : {
     406           6 :     while (GetLayerCount() > 0)
     407             :     {
     408           4 :         OGRErr eErr = DeleteLayer(0);
     409           4 :         if (eErr != OGRERR_NONE)
     410           0 :             return CE_Failure;
     411             :     }
     412           2 :     return CE_None;
     413             : }
     414             : 
     415         673 : CPLErr GNMFileNetwork::LoadNetworkLayer(const char *pszLayername)
     416             : {
     417             :     // check if not loaded
     418         983 :     for (size_t i = 0; i < m_apoLayers.size(); ++i)
     419             :     {
     420         962 :         if (EQUAL(m_apoLayers[i]->GetName(), pszLayername))
     421         652 :             return CE_None;
     422             :     }
     423             : 
     424          21 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     425             : 
     426             :     CPLString soFile =
     427          42 :         CPLFormFilename(m_soNetworkFullName, pszLayername, pszExt);
     428          21 :     GDALDataset *poDS = (GDALDataset *)GDALOpenEx(
     429             :         soFile, GDAL_OF_VECTOR | GDAL_OF_UPDATE, nullptr, nullptr, nullptr);
     430          21 :     if (nullptr == poDS)
     431             :     {
     432           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
     433             :                  soFile.c_str());
     434           0 :         return CE_Failure;
     435             :     }
     436             : 
     437          21 :     OGRLayer *poLayer = poDS->GetLayer(0);
     438          21 :     if (nullptr == poLayer)
     439             :     {
     440           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Layer '%s' is not exist",
     441             :                  pszLayername);
     442           0 :         return CE_Failure;
     443             :     }
     444             : 
     445          21 :     CPLDebug("GNM", "Layer '%s' loaded", poLayer->GetName());
     446             : 
     447          21 :     GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
     448          21 :     m_apoLayers.push_back(pGNMLayer);
     449          21 :     m_mpLayerDatasetMap[pGNMLayer] = poDS;
     450             : 
     451          21 :     return CE_None;
     452             : }
     453             : 
     454           2 : bool GNMFileNetwork::CheckStorageDriverSupport(const char *pszDriverName)
     455             : {
     456           2 :     if (EQUAL(pszDriverName, GNM_MD_DEFAULT_FILE_FORMAT))
     457           2 :         return true;
     458             :     // TODO: expand this list with supported OGR direvers
     459           0 :     return false;
     460             : }
     461             : 
     462           8 : CPLErr GNMFileNetwork::FormPath(const char *pszFilename, char **papszOptions)
     463             : {
     464           8 :     if (m_soNetworkFullName.empty())
     465             :     {
     466             :         const char *pszNetworkName =
     467           2 :             CSLFetchNameValue(papszOptions, GNM_MD_NAME);
     468           2 :         if (nullptr == pszNetworkName)
     469             :         {
     470           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     471             :                      "The network name should be present");
     472           0 :             return CE_Failure;
     473             :         }
     474             :         m_soNetworkFullName =
     475           2 :             CPLFormFilename(pszFilename, pszNetworkName, nullptr);
     476             : 
     477           2 :         CPLDebug("GNM", "Network name: %s", m_soNetworkFullName.c_str());
     478             :     }
     479           8 :     return CE_None;
     480             : }
     481             : 
     482           0 : int GNMFileNetwork::CloseDependentDatasets()
     483             : {
     484           0 :     size_t nCount = m_mpLayerDatasetMap.size();
     485           0 :     for (std::map<OGRLayer *, GDALDataset *>::iterator it =
     486           0 :              m_mpLayerDatasetMap.begin();
     487           0 :          it != m_mpLayerDatasetMap.end(); ++it)
     488             :     {
     489           0 :         GDALClose(it->second);
     490             :     }
     491             : 
     492           0 :     m_mpLayerDatasetMap.clear();
     493             : 
     494           0 :     GNMGenericNetwork::CloseDependentDatasets();
     495             : 
     496           0 :     return nCount > 0 ? TRUE : FALSE;
     497             : }
     498             : 
     499           4 : OGRErr GNMFileNetwork::DeleteLayer(int nIndex)
     500             : {
     501           4 :     OGRLayer *pLayer = GetLayer(nIndex);
     502             : 
     503           4 :     GDALDataset *poDS = m_mpLayerDatasetMap[pLayer];
     504           4 :     if (nullptr == poDS)
     505             :     {
     506           0 :         return OGRERR_FAILURE;
     507             :     }
     508             : 
     509           4 :     CPLDebug("GNM", "Delete network layer '%s'", pLayer->GetName());
     510             : 
     511           4 :     if (poDS->DeleteLayer(0) != OGRERR_NONE)
     512             :     {
     513           0 :         return OGRERR_FAILURE;
     514             :     }
     515             : 
     516           4 :     GDALClose(poDS);
     517             : 
     518             :     // remove pointer from map
     519           4 :     m_mpLayerDatasetMap.erase(pLayer);
     520             : 
     521           4 :     return GNMGenericNetwork::DeleteLayer(nIndex);
     522             : }
     523             : 
     524           4 : OGRLayer *GNMFileNetwork::ICreateLayer(const char *pszName,
     525             :                                        const OGRGeomFieldDefn *poGeomFieldDefn,
     526             :                                        CSLConstList papszOptions)
     527             : {
     528           4 :     if (nullptr == m_poLayerDriver)
     529             :     {
     530           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     531             :                  "The network storage format driver is not defined.");
     532           0 :         return nullptr;
     533             :     }
     534             : 
     535           4 :     const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     536             : 
     537             :     // check if layer with such name exist
     538           6 :     for (int i = 0; i < GetLayerCount(); ++i)
     539             :     {
     540           2 :         OGRLayer *pLayer = GetLayer(i);
     541           2 :         if (nullptr == pLayer)
     542           0 :             continue;
     543           2 :         if (EQUAL(pLayer->GetName(), pszName))
     544             :         {
     545           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     546             :                      "The network layer '%s' already exist.", pszName);
     547           0 :             return nullptr;
     548             :         }
     549             :     }
     550             : 
     551             :     // form path
     552           4 :     const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
     553           8 :     CPLString soPath = CPLFormFilename(m_soNetworkFullName, pszName, pszExt);
     554             : 
     555             :     GDALDataset *poDS =
     556           4 :         m_poLayerDriver->Create(soPath, 0, 0, 0, GDT_Unknown, papszOptions);
     557           4 :     if (poDS == nullptr)
     558             :     {
     559           0 :         CPLError(CE_Failure, CPLE_FileIO, "Creation of output file failed.");
     560           0 :         return nullptr;
     561             :     }
     562             : 
     563           8 :     OGRSpatialReference oSpaRef(m_oSRS);
     564             : 
     565             :     OGRLayer *poLayer =
     566           4 :         poDS->CreateLayer(pszName, &oSpaRef, eGType, papszOptions);
     567           4 :     if (poLayer == nullptr)
     568             :     {
     569           0 :         CPLError(CE_Failure, CPLE_FileIO, "Layer creation failed.");
     570           0 :         GDALClose(poDS);
     571           0 :         return nullptr;
     572             :     }
     573             : 
     574           8 :     OGRFieldDefn oField(GNM_SYSFIELD_GFID, GNMGFIDInt);
     575           4 :     if (poLayer->CreateField(&oField) != OGRERR_NONE)
     576             :     {
     577           0 :         CPLError(CE_Failure, CPLE_FileIO,
     578             :                  "Creating global identificator field failed.");
     579           0 :         GDALClose(poDS);
     580           0 :         return nullptr;
     581             :     }
     582             : 
     583           8 :     OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
     584           4 :     if (poLayer->CreateField(&oFieldBlock) != OGRERR_NONE)
     585             :     {
     586           0 :         CPLError(CE_Failure, CPLE_FileIO, "Creating is blocking field failed.");
     587           0 :         GDALClose(poDS);
     588           0 :         return nullptr;
     589             :     }
     590             : 
     591           4 :     GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
     592           4 :     m_apoLayers.push_back(pGNMLayer);
     593           4 :     m_mpLayerDatasetMap[pGNMLayer] = poDS;
     594           4 :     return pGNMLayer;
     595             : }
     596             : 
     597           2 : CPLErr GNMFileNetwork::Create(const char *pszFilename, char **papszOptions)
     598             : {
     599             :     // check required options
     600             : 
     601             :     // check name
     602           2 :     const char *pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
     603             : 
     604           2 :     if (nullptr == pszNetworkName)
     605             :     {
     606           0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     607             :                  "The network name should be present");
     608           0 :         return CE_Failure;
     609             :     }
     610             :     else
     611             :     {
     612           2 :         m_soName = pszNetworkName;
     613             :     }
     614             : 
     615             :     const char *pszNetworkDescription =
     616           2 :         CSLFetchNameValue(papszOptions, GNM_MD_DESCR);
     617           2 :     if (nullptr != pszNetworkDescription)
     618           2 :         sDescription = pszNetworkDescription;
     619             : 
     620             :     // check Spatial reference
     621           2 :     const char *pszSRS = CSLFetchNameValue(papszOptions, GNM_MD_SRS);
     622           2 :     if (nullptr == pszSRS)
     623             :     {
     624           0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     625             :                  "The network spatial reference should be present");
     626           0 :         return CE_Failure;
     627             :     }
     628             :     else
     629             :     {
     630           2 :         OGRSpatialReference spatialRef;
     631           2 :         spatialRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     632           2 :         if (spatialRef.SetFromUserInput(pszSRS) != OGRERR_NONE)
     633             :         {
     634           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
     635             :                      "The network spatial reference should be present");
     636           0 :             return CE_Failure;
     637             :         }
     638             : 
     639           2 :         m_oSRS = std::move(spatialRef);
     640             :     }
     641             : 
     642           2 :     int nResult = CheckNetworkExist(pszFilename, papszOptions);
     643             : 
     644           2 :     if (TRUE == nResult)
     645             :     {
     646           0 :         CPLError(CE_Failure, CPLE_IllegalArg, "The network already exist");
     647           0 :         return CE_Failure;
     648             :     }
     649             : 
     650             :     // Create the necessary system layers and fields
     651             : 
     652             :     // Create meta layer
     653             : 
     654             :     CPLErr eResult =
     655           2 :         CreateMetadataLayerFromFile(pszFilename, GNM_VERSION_NUM, papszOptions);
     656             : 
     657           2 :     if (CE_None != eResult)
     658             :     {
     659             :         // an error message should come from function
     660           0 :         return CE_Failure;
     661             :     }
     662             : 
     663             :     // Create graph layer
     664             : 
     665           2 :     eResult = CreateGraphLayerFromFile(pszFilename, papszOptions);
     666             : 
     667           2 :     if (CE_None != eResult)
     668             :     {
     669           0 :         DeleteMetadataLayer();
     670           0 :         return CE_Failure;
     671             :     }
     672             : 
     673             :     // Create features layer
     674             : 
     675           2 :     eResult = CreateFeaturesLayerFromFile(pszFilename, papszOptions);
     676             : 
     677           2 :     if (CE_None != eResult)
     678             :     {
     679           0 :         DeleteMetadataLayer();
     680           0 :         DeleteGraphLayer();
     681           0 :         return CE_Failure;
     682             :     }
     683             : 
     684           2 :     return CE_None;
     685             : }

Generated by: LCOV version 1.14