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 : }
|