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 49 : for (int i = 0; papszFiles[i] != nullptr; i++)
73 : {
74 49 : if (EQUAL(papszFiles[i], ".") || EQUAL(papszFiles[i], ".."))
75 0 : continue;
76 :
77 49 : 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 : CSLConstList 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 : CSLConstList 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 : CSLConstList 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 : CSLConstList 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,
465 : CSLConstList papszOptions)
466 : {
467 8 : if (m_soNetworkFullName.empty())
468 : {
469 : const char *pszNetworkName =
470 2 : CSLFetchNameValue(papszOptions, GNM_MD_NAME);
471 2 : if (nullptr == pszNetworkName)
472 : {
473 0 : CPLError(CE_Failure, CPLE_IllegalArg,
474 : "The network name should be present");
475 0 : return CE_Failure;
476 : }
477 : m_soNetworkFullName =
478 2 : CPLFormFilenameSafe(pszFilename, pszNetworkName, nullptr);
479 :
480 2 : CPLDebug("GNM", "Network name: %s", m_soNetworkFullName.c_str());
481 : }
482 8 : return CE_None;
483 : }
484 :
485 0 : int GNMFileNetwork::CloseDependentDatasets()
486 : {
487 0 : size_t nCount = m_mpLayerDatasetMap.size();
488 0 : for (std::map<OGRLayer *, GDALDataset *>::iterator it =
489 0 : m_mpLayerDatasetMap.begin();
490 0 : it != m_mpLayerDatasetMap.end(); ++it)
491 : {
492 0 : GDALClose(it->second);
493 : }
494 :
495 0 : m_mpLayerDatasetMap.clear();
496 :
497 0 : GNMGenericNetwork::CloseDependentDatasets();
498 :
499 0 : return nCount > 0 ? TRUE : FALSE;
500 : }
501 :
502 4 : OGRErr GNMFileNetwork::DeleteLayer(int nIndex)
503 : {
504 4 : OGRLayer *pLayer = GetLayer(nIndex);
505 :
506 4 : GDALDataset *poDS = m_mpLayerDatasetMap[pLayer];
507 4 : if (nullptr == poDS)
508 : {
509 0 : return OGRERR_FAILURE;
510 : }
511 :
512 4 : CPLDebug("GNM", "Delete network layer '%s'", pLayer->GetName());
513 :
514 4 : if (poDS->DeleteLayer(0) != OGRERR_NONE)
515 : {
516 0 : return OGRERR_FAILURE;
517 : }
518 :
519 4 : GDALClose(poDS);
520 :
521 : // remove pointer from map
522 4 : m_mpLayerDatasetMap.erase(pLayer);
523 :
524 4 : return GNMGenericNetwork::DeleteLayer(nIndex);
525 : }
526 :
527 4 : OGRLayer *GNMFileNetwork::ICreateLayer(const char *pszName,
528 : const OGRGeomFieldDefn *poGeomFieldDefn,
529 : CSLConstList papszOptions)
530 : {
531 4 : if (nullptr == m_poLayerDriver)
532 : {
533 0 : CPLError(CE_Failure, CPLE_AppDefined,
534 : "The network storage format driver is not defined.");
535 0 : return nullptr;
536 : }
537 :
538 4 : const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
539 :
540 : // check if layer with such name exist
541 6 : for (int i = 0; i < GetLayerCount(); ++i)
542 : {
543 2 : OGRLayer *pLayer = GetLayer(i);
544 2 : if (nullptr == pLayer)
545 0 : continue;
546 2 : if (EQUAL(pLayer->GetName(), pszName))
547 : {
548 0 : CPLError(CE_Failure, CPLE_IllegalArg,
549 : "The network layer '%s' already exist.", pszName);
550 0 : return nullptr;
551 : }
552 : }
553 :
554 : // form path
555 4 : const char *pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
556 : const CPLString soPath =
557 8 : CPLFormFilenameSafe(m_soNetworkFullName, pszName, pszExt);
558 :
559 : GDALDataset *poDS =
560 4 : m_poLayerDriver->Create(soPath, 0, 0, 0, GDT_Unknown, papszOptions);
561 4 : if (poDS == nullptr)
562 : {
563 0 : CPLError(CE_Failure, CPLE_FileIO, "Creation of output file failed.");
564 0 : return nullptr;
565 : }
566 :
567 8 : OGRSpatialReference oSpaRef(m_oSRS);
568 :
569 : OGRLayer *poLayer =
570 4 : poDS->CreateLayer(pszName, &oSpaRef, eGType, papszOptions);
571 4 : if (poLayer == nullptr)
572 : {
573 0 : CPLError(CE_Failure, CPLE_FileIO, "Layer creation failed.");
574 0 : GDALClose(poDS);
575 0 : return nullptr;
576 : }
577 :
578 8 : OGRFieldDefn oField(GNM_SYSFIELD_GFID, GNMGFIDInt);
579 4 : if (poLayer->CreateField(&oField) != OGRERR_NONE)
580 : {
581 0 : CPLError(CE_Failure, CPLE_FileIO,
582 : "Creating global identificator field failed.");
583 0 : GDALClose(poDS);
584 0 : return nullptr;
585 : }
586 :
587 8 : OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
588 4 : if (poLayer->CreateField(&oFieldBlock) != OGRERR_NONE)
589 : {
590 0 : CPLError(CE_Failure, CPLE_FileIO, "Creating is blocking field failed.");
591 0 : GDALClose(poDS);
592 0 : return nullptr;
593 : }
594 :
595 4 : GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
596 4 : m_apoLayers.push_back(pGNMLayer);
597 4 : m_mpLayerDatasetMap[pGNMLayer] = poDS;
598 4 : return pGNMLayer;
599 : }
600 :
601 2 : CPLErr GNMFileNetwork::Create(const char *pszFilename,
602 : CSLConstList papszOptions)
603 : {
604 : // check required options
605 :
606 : // check name
607 2 : const char *pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
608 :
609 2 : if (nullptr == pszNetworkName)
610 : {
611 0 : CPLError(CE_Failure, CPLE_IllegalArg,
612 : "The network name should be present");
613 0 : return CE_Failure;
614 : }
615 : else
616 : {
617 2 : m_soName = pszNetworkName;
618 : }
619 :
620 : const char *pszNetworkDescription =
621 2 : CSLFetchNameValue(papszOptions, GNM_MD_DESCR);
622 2 : if (nullptr != pszNetworkDescription)
623 2 : sDescription = pszNetworkDescription;
624 :
625 : // check Spatial reference
626 2 : const char *pszSRS = CSLFetchNameValue(papszOptions, GNM_MD_SRS);
627 2 : if (nullptr == pszSRS)
628 : {
629 0 : CPLError(CE_Failure, CPLE_IllegalArg,
630 : "The network spatial reference should be present");
631 0 : return CE_Failure;
632 : }
633 : else
634 : {
635 2 : OGRSpatialReference spatialRef;
636 2 : spatialRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
637 2 : if (spatialRef.SetFromUserInput(pszSRS) != OGRERR_NONE)
638 : {
639 0 : CPLError(CE_Failure, CPLE_IllegalArg,
640 : "The network spatial reference should be present");
641 0 : return CE_Failure;
642 : }
643 :
644 2 : m_oSRS = std::move(spatialRef);
645 : }
646 :
647 2 : int nResult = CheckNetworkExist(pszFilename, papszOptions);
648 :
649 2 : if (TRUE == nResult)
650 : {
651 0 : CPLError(CE_Failure, CPLE_IllegalArg, "The network already exist");
652 0 : return CE_Failure;
653 : }
654 :
655 : // Create the necessary system layers and fields
656 :
657 : // Create meta layer
658 :
659 : CPLErr eResult =
660 2 : CreateMetadataLayerFromFile(pszFilename, GNM_VERSION_NUM, papszOptions);
661 :
662 2 : if (CE_None != eResult)
663 : {
664 : // an error message should come from function
665 0 : return CE_Failure;
666 : }
667 :
668 : // Create graph layer
669 :
670 2 : eResult = CreateGraphLayerFromFile(pszFilename, papszOptions);
671 :
672 2 : if (CE_None != eResult)
673 : {
674 0 : DeleteMetadataLayer();
675 0 : return CE_Failure;
676 : }
677 :
678 : // Create features layer
679 :
680 2 : eResult = CreateFeaturesLayerFromFile(pszFilename, papszOptions);
681 :
682 2 : if (CE_None != eResult)
683 : {
684 0 : DeleteMetadataLayer();
685 0 : DeleteGraphLayer();
686 0 : return CE_Failure;
687 : }
688 :
689 2 : return CE_None;
690 : }
|