Coverage Report

Created: 2025-06-13 06:29

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