Line data Source code
1 : /******************************************************************************
2 : * Project: OGR
3 : * Purpose: OGRGMLASDriver implementation
4 : * Author: Even Rouault, <even dot rouault at spatialys dot com>
5 : *
6 : * Initial development funded by the European Earth observation programme
7 : * Copernicus
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #include "ogr_gmlas.h"
16 : #include "ogr_pgdump.h"
17 : #include "cpl_minixml.h"
18 :
19 : /************************************************************************/
20 : /* OGRGMLASLayer() */
21 : /************************************************************************/
22 :
23 15271 : OGRGMLASLayer::OGRGMLASLayer(OGRGMLASDataSource *poDS,
24 : const GMLASFeatureClass &oFC,
25 : OGRGMLASLayer *poParentLayer,
26 15271 : bool bAlwaysGenerateOGRPKId)
27 : : m_poDS(poDS), m_oFC(oFC),
28 15271 : m_poFeatureDefn(new OGRFeatureDefn(oFC.GetName())),
29 30542 : m_poParentLayer(poParentLayer)
30 : {
31 15271 : m_poFeatureDefn->SetGeomType(wkbNone);
32 15271 : m_poFeatureDefn->Reference();
33 :
34 15271 : SetDescription(m_poFeatureDefn->GetName());
35 :
36 : // Are we a regular table ?
37 15271 : if (m_oFC.GetParentXPath().empty())
38 : {
39 6407 : if (bAlwaysGenerateOGRPKId)
40 : {
41 46 : OGRFieldDefn oFieldDefn(szOGR_PKID, OFTString);
42 23 : oFieldDefn.SetNullable(false);
43 23 : m_nIDFieldIdx = m_poFeatureDefn->GetFieldCount();
44 23 : m_bIDFieldIsGenerated = true;
45 23 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
46 : }
47 :
48 : // Determine if we have an xs:ID attribute/elt, and if it is compulsory,
49 : // If so, place it as first field (not strictly required, but more
50 : // readable) or second field (if we also add a ogr_pkid) Furthermore
51 : // restrict that to attributes, because otherwise it is impractical in
52 : // the reader when joining related features.
53 6407 : const std::vector<GMLASField> &oFields = m_oFC.GetFields();
54 189925 : for (int i = 0; i < static_cast<int>(oFields.size()); i++)
55 : {
56 189499 : if (oFields[i].GetType() == GMLAS_FT_ID &&
57 189499 : oFields[i].IsNotNullable() &&
58 209 : oFields[i].GetXPath().find('@') != std::string::npos)
59 : {
60 108 : OGRFieldDefn oFieldDefn(oFields[i].GetName(), OFTString);
61 54 : oFieldDefn.SetNullable(false);
62 54 : const int nOGRIdx = m_poFeatureDefn->GetFieldCount();
63 54 : if (m_nIDFieldIdx < 0)
64 53 : m_nIDFieldIdx = nOGRIdx;
65 54 : m_oMapFieldXPathToOGRFieldIdx[oFields[i].GetXPath()] = nOGRIdx;
66 54 : m_oMapOGRFieldIdxtoFCFieldIdx[nOGRIdx] = i;
67 54 : m_oMapFieldXPathToFCFieldIdx[oFields[i].GetXPath()] = i;
68 54 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
69 54 : break;
70 : }
71 : }
72 :
73 : // If we don't have an explicit ID, then we need
74 : // to generate one, so that potentially related classes can reference it
75 : // (We could perhaps try to be clever to determine if we really need it)
76 6407 : if (m_nIDFieldIdx < 0)
77 : {
78 12662 : OGRFieldDefn oFieldDefn(szOGR_PKID, OFTString);
79 6331 : oFieldDefn.SetNullable(false);
80 6331 : m_nIDFieldIdx = m_poFeatureDefn->GetFieldCount();
81 6331 : m_bIDFieldIsGenerated = true;
82 6331 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
83 : }
84 : }
85 :
86 15271 : OGRLayer *poLayersMetadataLayer = m_poDS->GetLayersMetadataLayer();
87 : OGRFeature *poLayerDescFeature =
88 15271 : new OGRFeature(poLayersMetadataLayer->GetLayerDefn());
89 15271 : poLayerDescFeature->SetField(szLAYER_NAME, OGRGMLASLayer::GetName());
90 15271 : if (!m_oFC.GetParentXPath().empty())
91 : {
92 8864 : poLayerDescFeature->SetField(szLAYER_CATEGORY, szJUNCTION_TABLE);
93 : }
94 : else
95 : {
96 6407 : poLayerDescFeature->SetField(szLAYER_XPATH, m_oFC.GetXPath());
97 :
98 6407 : poLayerDescFeature->SetField(szLAYER_CATEGORY, m_oFC.IsTopLevelElt()
99 : ? szTOP_LEVEL_ELEMENT
100 : : szNESTED_ELEMENT);
101 :
102 6407 : if (m_nIDFieldIdx >= 0)
103 : {
104 6407 : poLayerDescFeature->SetField(
105 : szLAYER_PKID_NAME,
106 6407 : m_poFeatureDefn->GetFieldDefn(m_nIDFieldIdx)->GetNameRef());
107 : }
108 :
109 : // If we are a child class, then add a field to reference the parent.
110 6407 : if (m_poParentLayer != nullptr)
111 : {
112 6618 : CPLString osFieldName(szPARENT_PREFIX);
113 3309 : osFieldName += m_poParentLayer->GetLayerDefn()
114 3309 : ->GetFieldDefn(m_poParentLayer->GetIDFieldIdx())
115 3309 : ->GetNameRef();
116 3309 : poLayerDescFeature->SetField(szLAYER_PARENT_PKID_NAME,
117 : osFieldName.c_str());
118 : }
119 :
120 6407 : if (!m_oFC.GetDocumentation().empty())
121 : {
122 5065 : poLayerDescFeature->SetField(szLAYER_DOCUMENTATION,
123 5065 : m_oFC.GetDocumentation());
124 : }
125 : }
126 15271 : CPL_IGNORE_RET_VAL(
127 15271 : poLayersMetadataLayer->CreateFeature(poLayerDescFeature));
128 15271 : delete poLayerDescFeature;
129 15271 : }
130 :
131 : /************************************************************************/
132 : /* OGRGMLASLayer() */
133 : /************************************************************************/
134 :
135 3 : OGRGMLASLayer::OGRGMLASLayer(const char *pszLayerName)
136 : : m_bLayerDefnFinalized(true),
137 3 : m_poFeatureDefn(new OGRFeatureDefn(pszLayerName))
138 :
139 : {
140 3 : m_poFeatureDefn->SetGeomType(wkbNone);
141 3 : m_poFeatureDefn->Reference();
142 :
143 3 : SetDescription(m_poFeatureDefn->GetName());
144 3 : }
145 :
146 : /************************************************************************/
147 : /* GetSWEChildAndType() */
148 : /************************************************************************/
149 :
150 36 : static CPLXMLNode *GetSWEChildAndType(CPLXMLNode *psNode, OGRFieldType &eType,
151 : OGRFieldSubType &eSubType)
152 : {
153 36 : eType = OFTString;
154 36 : eSubType = OFSTNone;
155 36 : CPLXMLNode *psChildNode = nullptr;
156 36 : if ((psChildNode = CPLGetXMLNode(psNode, "Time")) != nullptr)
157 : {
158 8 : eType = OFTDateTime;
159 : }
160 28 : else if ((psChildNode = CPLGetXMLNode(psNode, "Quantity")) != nullptr)
161 : {
162 8 : eType = OFTReal;
163 : }
164 20 : else if ((psChildNode = CPLGetXMLNode(psNode, "Category")) != nullptr)
165 : {
166 8 : eType = OFTString;
167 : }
168 12 : else if ((psChildNode = CPLGetXMLNode(psNode, "Count")) != nullptr)
169 : {
170 4 : eType = OFTInteger;
171 : }
172 8 : else if ((psChildNode = CPLGetXMLNode(psNode, "Text")) != nullptr)
173 : {
174 4 : eType = OFTString;
175 : }
176 4 : else if ((psChildNode = CPLGetXMLNode(psNode, "Boolean")) != nullptr)
177 : {
178 4 : eType = OFTInteger;
179 4 : eSubType = OFSTBoolean;
180 : }
181 36 : return psChildNode;
182 : }
183 :
184 : /************************************************************************/
185 : /* ProcessDataRecordOfDataArrayCreateFields() */
186 : /************************************************************************/
187 :
188 3 : void OGRGMLASLayer::ProcessDataRecordOfDataArrayCreateFields(
189 : OGRGMLASLayer *poParentLayer, CPLXMLNode *psDataRecord,
190 : OGRLayer *poFieldsMetadataLayer)
191 : {
192 : {
193 6 : CPLString osFieldName(szPARENT_PREFIX);
194 3 : osFieldName += poParentLayer->GetLayerDefn()
195 3 : ->GetFieldDefn(poParentLayer->GetIDFieldIdx())
196 3 : ->GetNameRef();
197 6 : OGRFieldDefn oFieldDefn(osFieldName, OFTString);
198 3 : oFieldDefn.SetNullable(false);
199 3 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
200 : }
201 :
202 30 : for (CPLXMLNode *psIter = psDataRecord->psChild; psIter != nullptr;
203 27 : psIter = psIter->psNext)
204 : {
205 27 : if (psIter->eType == CXT_Element &&
206 12 : strcmp(psIter->pszValue, "field") == 0)
207 : {
208 12 : const char *pszName = CPLGetXMLValue(psIter, "name", "");
209 24 : OGRFieldDefn oFieldDefn(CPLString(pszName).tolower(), OFTString);
210 : OGRFieldType eType;
211 : OGRFieldSubType eSubType;
212 12 : CPLXMLNode *psNode = GetSWEChildAndType(psIter, eType, eSubType);
213 12 : oFieldDefn.SetType(eType);
214 12 : oFieldDefn.SetSubType(eSubType);
215 12 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
216 :
217 : // Register field in _ogr_fields_metadata
218 : OGRFeature *poFieldDescFeature =
219 12 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
220 12 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
221 12 : m_nMaxFieldIndex = m_poFeatureDefn->GetFieldCount() - 1;
222 12 : poFieldDescFeature->SetField(szFIELD_INDEX, m_nMaxFieldIndex);
223 12 : poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());
224 12 : if (psNode)
225 : {
226 12 : poFieldDescFeature->SetField(szFIELD_TYPE, psNode->pszValue);
227 : }
228 12 : poFieldDescFeature->SetField(szFIELD_IS_LIST, 0);
229 12 : poFieldDescFeature->SetField(szFIELD_MIN_OCCURS, 0);
230 12 : poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, 1);
231 12 : poFieldDescFeature->SetField(szFIELD_CATEGORY, szSWE_FIELD);
232 12 : if (psNode)
233 : {
234 12 : char *pszXML = CPLSerializeXMLTree(psNode);
235 12 : poFieldDescFeature->SetField(szFIELD_DOCUMENTATION, pszXML);
236 12 : CPLFree(pszXML);
237 : }
238 12 : CPL_IGNORE_RET_VAL(
239 12 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
240 12 : delete poFieldDescFeature;
241 : }
242 : }
243 3 : }
244 :
245 : /************************************************************************/
246 : /* ProcessDataRecordCreateFields() */
247 : /************************************************************************/
248 :
249 4 : void OGRGMLASLayer::ProcessDataRecordCreateFields(
250 : CPLXMLNode *psDataRecord, const std::vector<OGRFeature *> &apoFeatures,
251 : OGRLayer *poFieldsMetadataLayer)
252 : {
253 33 : for (CPLXMLNode *psIter = psDataRecord->psChild; psIter != nullptr;
254 29 : psIter = psIter->psNext)
255 : {
256 29 : if (psIter->eType == CXT_Element &&
257 18 : strcmp(psIter->pszValue, "field") == 0)
258 : {
259 18 : const char *pszName = CPLGetXMLValue(psIter, "name", "");
260 36 : CPLString osName = CPLString(pszName).tolower();
261 36 : OGRFieldDefn oFieldDefn(osName, OFTString);
262 : OGRFieldType eType;
263 : OGRFieldSubType eSubType;
264 : CPLXMLNode *psChildNode =
265 18 : GetSWEChildAndType(psIter, eType, eSubType);
266 18 : oFieldDefn.SetType(eType);
267 18 : oFieldDefn.SetSubType(eSubType);
268 36 : if (psChildNode != nullptr &&
269 18 : m_oMapSWEFieldToOGRFieldName.find(osName) ==
270 36 : m_oMapSWEFieldToOGRFieldName.end())
271 : {
272 12 : const int nValidFields = m_poFeatureDefn->GetFieldCount();
273 :
274 24 : CPLString osSWEField(osName);
275 12 : if (m_poFeatureDefn->GetFieldIndex(osName) >= 0)
276 0 : osName = "swe_field_" + osName;
277 12 : m_oMapSWEFieldToOGRFieldName[osSWEField] = osName;
278 12 : oFieldDefn.SetName((osName + "_value").c_str());
279 12 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
280 :
281 : // Register field in _ogr_fields_metadata
282 : OGRFeature *poFieldDescFeature =
283 12 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
284 12 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
285 12 : m_nMaxFieldIndex++;
286 12 : poFieldDescFeature->SetField(szFIELD_INDEX, m_nMaxFieldIndex);
287 12 : poFieldDescFeature->SetField(szFIELD_NAME,
288 : oFieldDefn.GetNameRef());
289 12 : poFieldDescFeature->SetField(szFIELD_TYPE,
290 12 : psChildNode->pszValue);
291 12 : poFieldDescFeature->SetField(szFIELD_IS_LIST, 0);
292 12 : poFieldDescFeature->SetField(szFIELD_MIN_OCCURS, 0);
293 12 : poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, 1);
294 12 : poFieldDescFeature->SetField(szFIELD_CATEGORY, szSWE_FIELD);
295 : {
296 12 : CPLXMLNode *psDupTree = CPLCloneXMLTree(psChildNode);
297 12 : CPLXMLNode *psValue = CPLGetXMLNode(psDupTree, "value");
298 12 : if (psValue != nullptr)
299 : {
300 12 : CPLRemoveXMLChild(psDupTree, psValue);
301 12 : CPLDestroyXMLNode(psValue);
302 : }
303 12 : char *pszXML = CPLSerializeXMLTree(psDupTree);
304 12 : CPLDestroyXMLNode(psDupTree);
305 12 : poFieldDescFeature->SetField(szFIELD_DOCUMENTATION, pszXML);
306 12 : CPLFree(pszXML);
307 : }
308 12 : CPL_IGNORE_RET_VAL(
309 12 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
310 12 : delete poFieldDescFeature;
311 :
312 12 : for (CPLXMLNode *psIter2 = psChildNode->psChild;
313 55 : psIter2 != nullptr; psIter2 = psIter2->psNext)
314 : {
315 43 : if (psIter2->eType == CXT_Element &&
316 16 : strcmp(psIter2->pszValue, "value") != 0)
317 : {
318 : const CPLString osName2 =
319 8 : CPLString(osName + "_" + psIter2->pszValue)
320 8 : .tolower();
321 4 : for (CPLXMLNode *psIter3 = psIter2->psChild;
322 8 : psIter3 != nullptr; psIter3 = psIter3->psNext)
323 : {
324 4 : if (psIter3->eType == CXT_Attribute)
325 : {
326 2 : const char *pszValue = psIter3->pszValue;
327 2 : const char *pszColon = strchr(pszValue, ':');
328 2 : if (pszColon)
329 2 : pszValue = pszColon + 1;
330 : OGRFieldDefn oFieldDefn2(
331 4 : CPLString(osName2 + "_" + pszValue)
332 2 : .tolower(),
333 4 : OFTString);
334 2 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn2);
335 : }
336 2 : else if (psIter3->eType == CXT_Text)
337 : {
338 4 : OGRFieldDefn oFieldDefn2(osName2, OFTString);
339 2 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn2);
340 : }
341 : }
342 : }
343 : }
344 :
345 : int *panRemap = static_cast<int *>(
346 12 : CPLMalloc(sizeof(int) * m_poFeatureDefn->GetFieldCount()));
347 122 : for (int i = 0; i < m_poFeatureDefn->GetFieldCount(); ++i)
348 : {
349 110 : if (i < nValidFields)
350 94 : panRemap[i] = i;
351 : else
352 16 : panRemap[i] = -1;
353 : }
354 :
355 24 : for (size_t i = 0; i < apoFeatures.size(); i++)
356 : {
357 12 : apoFeatures[i]->RemapFields(nullptr, panRemap);
358 : }
359 :
360 12 : CPLFree(panRemap);
361 : }
362 : }
363 : }
364 4 : }
365 :
366 : /************************************************************************/
367 : /* SetSWEValue() */
368 : /************************************************************************/
369 :
370 8 : static void SetSWEValue(OGRFeature *poFeature, const CPLString &osFieldName,
371 : const char *pszValue)
372 : {
373 8 : int iField = poFeature->GetDefnRef()->GetFieldIndex(osFieldName);
374 8 : OGRFieldDefn *poFieldDefn = poFeature->GetFieldDefnRef(iField);
375 8 : OGRFieldType eType(poFieldDefn->GetType());
376 8 : OGRFieldSubType eSubType(poFieldDefn->GetSubType());
377 8 : if (eType == OFTInteger && eSubType == OFSTBoolean)
378 : {
379 1 : poFeature->SetField(
380 1 : iField, EQUAL(pszValue, "1") || EQUAL(pszValue, "True") ? 1 : 0);
381 : }
382 : else
383 : {
384 7 : poFeature->SetField(iField, pszValue);
385 : }
386 8 : }
387 :
388 : /************************************************************************/
389 : /* ProcessDataRecordFillFeature() */
390 : /************************************************************************/
391 :
392 1 : void OGRGMLASLayer::ProcessDataRecordFillFeature(CPLXMLNode *psDataRecord,
393 : OGRFeature *poFeature)
394 : {
395 14 : for (CPLXMLNode *psIter = psDataRecord->psChild; psIter != nullptr;
396 13 : psIter = psIter->psNext)
397 : {
398 13 : if (psIter->eType == CXT_Element &&
399 6 : strcmp(psIter->pszValue, "field") == 0)
400 : {
401 6 : const char *pszName = CPLGetXMLValue(psIter, "name", "");
402 6 : CPLString osName = CPLString(pszName).tolower();
403 6 : OGRFieldDefn oFieldDefn(osName, OFTString);
404 : OGRFieldType eType;
405 : OGRFieldSubType eSubType;
406 : CPLXMLNode *psChildNode =
407 6 : GetSWEChildAndType(psIter, eType, eSubType);
408 6 : oFieldDefn.SetType(eType);
409 6 : oFieldDefn.SetSubType(eSubType);
410 6 : if (psChildNode == nullptr)
411 0 : continue;
412 6 : const auto oIter = m_oMapSWEFieldToOGRFieldName.find(osName);
413 6 : CPLAssert(oIter != m_oMapSWEFieldToOGRFieldName.end());
414 6 : osName = oIter->second;
415 34 : for (CPLXMLNode *psIter2 = psChildNode->psChild; psIter2 != nullptr;
416 28 : psIter2 = psIter2->psNext)
417 : {
418 28 : if (psIter2->eType == CXT_Element)
419 : {
420 : const CPLString osName2 =
421 24 : CPLString(osName + "_" + psIter2->pszValue).tolower();
422 8 : for (CPLXMLNode *psIter3 = psIter2->psChild;
423 16 : psIter3 != nullptr; psIter3 = psIter3->psNext)
424 : {
425 8 : if (psIter3->eType == CXT_Attribute)
426 : {
427 1 : const char *pszValue = psIter3->pszValue;
428 1 : const char *pszColon = strchr(pszValue, ':');
429 1 : if (pszColon)
430 1 : pszValue = pszColon + 1;
431 1 : SetSWEValue(
432 : poFeature,
433 1 : CPLString(osName2 + "_" + pszValue).tolower(),
434 1 : psIter3->psChild->pszValue);
435 : }
436 7 : else if (psIter3->eType == CXT_Text)
437 : {
438 7 : SetSWEValue(poFeature, osName2, psIter3->pszValue);
439 : }
440 : }
441 : }
442 : }
443 : }
444 : }
445 1 : }
446 :
447 : /************************************************************************/
448 : /* PostInit() */
449 : /************************************************************************/
450 :
451 15271 : void OGRGMLASLayer::PostInit(bool bIncludeGeometryXML)
452 : {
453 15271 : const std::vector<GMLASField> &oFields = m_oFC.GetFields();
454 :
455 15271 : OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();
456 15271 : OGRLayer *poRelationshipsLayer = m_poDS->GetRelationshipsLayer();
457 :
458 : // Is it a junction table ?
459 15271 : if (!m_oFC.GetParentXPath().empty())
460 : {
461 : {
462 17728 : OGRFieldDefn oFieldDefn(szOCCURRENCE, OFTInteger);
463 8864 : oFieldDefn.SetNullable(false);
464 8864 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
465 :
466 : OGRFeature *poFieldDescFeature =
467 8864 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
468 8864 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
469 8864 : poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());
470 8864 : CPL_IGNORE_RET_VAL(
471 8864 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
472 8864 : delete poFieldDescFeature;
473 : }
474 :
475 : {
476 17728 : OGRFieldDefn oFieldDefn(szPARENT_PKID, OFTString);
477 8864 : oFieldDefn.SetNullable(false);
478 8864 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
479 :
480 : OGRFeature *poFieldDescFeature =
481 8864 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
482 8864 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
483 8864 : poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());
484 8864 : CPL_IGNORE_RET_VAL(
485 8864 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
486 8864 : delete poFieldDescFeature;
487 : }
488 : {
489 17728 : OGRFieldDefn oFieldDefn(szCHILD_PKID, OFTString);
490 8864 : oFieldDefn.SetNullable(false);
491 8864 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
492 :
493 : OGRFeature *poFieldDescFeature =
494 8864 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
495 8864 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
496 8864 : poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());
497 8864 : CPL_IGNORE_RET_VAL(
498 8864 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
499 8864 : delete poFieldDescFeature;
500 : }
501 :
502 8864 : return;
503 : }
504 :
505 : // If we are a child class, then add a field to reference the parent.
506 6407 : if (m_poParentLayer != nullptr)
507 : {
508 6618 : CPLString osFieldName(szPARENT_PREFIX);
509 3309 : osFieldName += m_poParentLayer->GetLayerDefn()
510 3309 : ->GetFieldDefn(m_poParentLayer->GetIDFieldIdx())
511 3309 : ->GetNameRef();
512 6618 : OGRFieldDefn oFieldDefn(osFieldName, OFTString);
513 3309 : oFieldDefn.SetNullable(false);
514 3309 : m_nParentIDFieldIdx = m_poFeatureDefn->GetFieldCount();
515 3309 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
516 : }
517 :
518 6407 : int nFieldIndex = 0;
519 194062 : for (int i = 0; i < static_cast<int>(oFields.size()); i++)
520 : {
521 187655 : OGRGMLASLayer *poRelatedLayer = nullptr;
522 187655 : const GMLASField &oField(oFields[i]);
523 :
524 187655 : m_oMapFieldXPathToFCFieldIdx[oField.GetXPath()] = i;
525 187655 : if (oField.IsIgnored())
526 13857 : continue;
527 :
528 187645 : const GMLASField::Category eCategory(oField.GetCategory());
529 187645 : if (!oField.GetRelatedClassXPath().empty())
530 : {
531 : poRelatedLayer =
532 19471 : m_poDS->GetLayerByXPath(oField.GetRelatedClassXPath());
533 19471 : if (poRelatedLayer != nullptr)
534 : {
535 : OGRFeature *poRelationshipsFeature =
536 18308 : new OGRFeature(poRelationshipsLayer->GetLayerDefn());
537 18308 : poRelationshipsFeature->SetField(szPARENT_LAYER, GetName());
538 18308 : poRelationshipsFeature->SetField(
539 18308 : szPARENT_PKID, GetLayerDefn()
540 18308 : ->GetFieldDefn(GetIDFieldIdx())
541 : ->GetNameRef());
542 18308 : if (!oField.GetName().empty())
543 : {
544 18090 : poRelationshipsFeature->SetField(szPARENT_ELEMENT_NAME,
545 18090 : oField.GetName());
546 : }
547 18308 : poRelationshipsFeature->SetField(szCHILD_LAYER,
548 : poRelatedLayer->GetName());
549 18308 : if (eCategory ==
550 9474 : GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||
551 : eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK)
552 : {
553 14999 : poRelationshipsFeature->SetField(
554 : szCHILD_PKID,
555 14999 : poRelatedLayer->GetLayerDefn()
556 14999 : ->GetFieldDefn(poRelatedLayer->GetIDFieldIdx())
557 : ->GetNameRef());
558 : }
559 : else
560 : {
561 3309 : CPLAssert(eCategory ==
562 : GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
563 : eCategory == GMLASField::GROUP);
564 :
565 3309 : poRelationshipsFeature->SetField(
566 6618 : szCHILD_PKID, (CPLString(szPARENT_PREFIX) +
567 3309 : GetLayerDefn()
568 3309 : ->GetFieldDefn(GetIDFieldIdx())
569 : ->GetNameRef())
570 : .c_str());
571 : }
572 18308 : CPL_IGNORE_RET_VAL(poRelationshipsLayer->CreateFeature(
573 : poRelationshipsFeature));
574 18308 : delete poRelationshipsFeature;
575 : }
576 : else
577 : {
578 1163 : CPLDebug("GMLAS", "Cannot find class matching %s",
579 1163 : oField.GetRelatedClassXPath().c_str());
580 : }
581 : }
582 :
583 : OGRFeature *poFieldDescFeature =
584 187645 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
585 187645 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
586 :
587 187645 : ++nFieldIndex;
588 187645 : m_nMaxFieldIndex = nFieldIndex;
589 187645 : poFieldDescFeature->SetField(szFIELD_INDEX, nFieldIndex);
590 :
591 187645 : if (oField.GetName().empty())
592 : {
593 218 : CPLAssert(eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
594 : eCategory == GMLASField::GROUP);
595 : }
596 : else
597 : {
598 187427 : poFieldDescFeature->SetField(szFIELD_NAME,
599 187427 : oField.GetName().c_str());
600 : }
601 187645 : if (!oField.GetXPath().empty())
602 : {
603 187391 : poFieldDescFeature->SetField(szFIELD_XPATH,
604 187391 : oField.GetXPath().c_str());
605 : }
606 254 : else if (!oField.GetAlternateXPaths().empty())
607 : {
608 166 : CPLString osXPath;
609 : const std::vector<CPLString> &aoXPaths =
610 83 : oField.GetAlternateXPaths();
611 818 : for (size_t j = 0; j < aoXPaths.size(); j++)
612 : {
613 735 : if (j != 0)
614 652 : osXPath += ",";
615 735 : osXPath += aoXPaths[j];
616 : }
617 83 : poFieldDescFeature->SetField(szFIELD_XPATH, osXPath.c_str());
618 : }
619 187645 : if (oField.GetTypeName().empty())
620 : {
621 13306 : CPLAssert(
622 : eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
623 : eCategory ==
624 : GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||
625 : eCategory == GMLASField::GROUP);
626 : }
627 : else
628 : {
629 174339 : poFieldDescFeature->SetField(szFIELD_TYPE,
630 174339 : oField.GetTypeName().c_str());
631 : }
632 187645 : poFieldDescFeature->SetField(szFIELD_IS_LIST,
633 187645 : static_cast<int>(oField.IsList()));
634 187645 : if (oField.GetMinOccurs() != -1)
635 : {
636 187456 : poFieldDescFeature->SetField(szFIELD_MIN_OCCURS,
637 : oField.GetMinOccurs());
638 : }
639 187645 : if (oField.GetMaxOccurs() == MAXOCCURS_UNLIMITED)
640 : {
641 12731 : poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, INT_MAX);
642 : }
643 174914 : else if (oField.GetMaxOccurs() != -1)
644 : {
645 174678 : poFieldDescFeature->SetField(szFIELD_MAX_OCCURS,
646 : oField.GetMaxOccurs());
647 : }
648 362559 : if (oField.GetMaxOccurs() == MAXOCCURS_UNLIMITED ||
649 174914 : oField.GetMaxOccurs() > 1)
650 : {
651 14374 : poFieldDescFeature->SetField(szFIELD_REPETITION_ON_SEQUENCE,
652 14374 : oField.GetRepetitionOnSequence() ? 1
653 : : 0);
654 : }
655 187645 : if (!oField.GetFixedValue().empty())
656 : {
657 415 : poFieldDescFeature->SetField(szFIELD_FIXED_VALUE,
658 415 : oField.GetFixedValue());
659 : }
660 187645 : if (!oField.GetDefaultValue().empty())
661 : {
662 221 : poFieldDescFeature->SetField(szFIELD_DEFAULT_VALUE,
663 221 : oField.GetDefaultValue());
664 : }
665 187645 : switch (eCategory)
666 : {
667 168174 : case GMLASField::REGULAR:
668 168174 : poFieldDescFeature->SetField(szFIELD_CATEGORY, szREGULAR);
669 168174 : break;
670 4307 : case GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK:
671 4307 : poFieldDescFeature->SetField(szFIELD_CATEGORY,
672 : szPATH_TO_CHILD_ELEMENT_NO_LINK);
673 4307 : break;
674 6165 : case GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK:
675 6165 : poFieldDescFeature->SetField(szFIELD_CATEGORY,
676 : szPATH_TO_CHILD_ELEMENT_WITH_LINK);
677 6165 : break;
678 8834 : case GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE:
679 8834 : poFieldDescFeature->SetField(
680 : szFIELD_CATEGORY,
681 : szPATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE);
682 8834 : break;
683 165 : case GMLASField::GROUP:
684 165 : poFieldDescFeature->SetField(szFIELD_CATEGORY, szGROUP);
685 165 : break;
686 0 : default:
687 0 : CPLAssert(FALSE);
688 : break;
689 : }
690 187645 : if (poRelatedLayer != nullptr)
691 : {
692 18308 : poFieldDescFeature->SetField(szFIELD_RELATED_LAYER,
693 : poRelatedLayer->GetName());
694 : }
695 :
696 187645 : if (eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE)
697 : {
698 : const CPLString &osAbstractElementXPath(
699 8834 : oField.GetAbstractElementXPath());
700 8834 : const CPLString &osNestedXPath(oField.GetRelatedClassXPath());
701 8834 : CPLAssert(!osAbstractElementXPath.empty());
702 8834 : CPLAssert(!osNestedXPath.empty());
703 :
704 8834 : OGRGMLASLayer *poJunctionLayer = m_poDS->GetLayerByXPath(
705 17668 : osAbstractElementXPath + "|" + osNestedXPath);
706 8834 : if (poJunctionLayer != nullptr)
707 : {
708 8834 : poFieldDescFeature->SetField(szFIELD_JUNCTION_LAYER,
709 : poJunctionLayer->GetName());
710 : }
711 : }
712 :
713 187645 : if (!oField.GetDocumentation().empty())
714 : {
715 141878 : poFieldDescFeature->SetField(szFIELD_DOCUMENTATION,
716 141878 : oField.GetDocumentation());
717 : }
718 :
719 187645 : CPL_IGNORE_RET_VAL(
720 187645 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
721 187645 : delete poFieldDescFeature;
722 :
723 : // Check whether the field is OGR instanciable
724 187645 : if (eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
725 : eCategory ==
726 174504 : GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||
727 : eCategory == GMLASField::GROUP)
728 : {
729 13306 : continue;
730 : }
731 :
732 174339 : OGRFieldType eType = OFTString;
733 174339 : OGRFieldSubType eSubType = OFSTNone;
734 174339 : CPLString osOGRFieldName(oField.GetName());
735 174339 : switch (oField.GetType())
736 : {
737 112983 : case GMLAS_FT_STRING:
738 112983 : eType = OFTString;
739 112983 : break;
740 6017 : case GMLAS_FT_ID:
741 : {
742 6017 : eType = OFTString;
743 6017 : if (oField.IsNotNullable())
744 : {
745 209 : continue;
746 : }
747 5808 : break;
748 : }
749 1235 : case GMLAS_FT_BOOLEAN:
750 1235 : eType = OFTInteger;
751 1235 : eSubType = OFSTBoolean;
752 1235 : break;
753 47 : case GMLAS_FT_SHORT:
754 47 : eType = OFTInteger;
755 47 : eSubType = OFSTInt16;
756 47 : break;
757 1932 : case GMLAS_FT_INT32:
758 1932 : eType = OFTInteger;
759 1932 : break;
760 19179 : case GMLAS_FT_INT64:
761 19179 : eType = OFTInteger64;
762 19179 : break;
763 94 : case GMLAS_FT_FLOAT:
764 94 : eType = OFTReal;
765 94 : eSubType = OFSTFloat32;
766 94 : break;
767 28925 : case GMLAS_FT_DOUBLE:
768 28925 : eType = OFTReal;
769 28925 : break;
770 53 : case GMLAS_FT_DECIMAL:
771 53 : eType = OFTReal;
772 53 : break;
773 47 : case GMLAS_FT_DATE:
774 47 : eType = OFTDate;
775 47 : break;
776 0 : case GMLAS_FT_GYEAR:
777 0 : eType = OFTInteger;
778 0 : break;
779 0 : case GMLAS_FT_GYEAR_MONTH:
780 0 : eType = OFTDate;
781 0 : break;
782 47 : case GMLAS_FT_TIME:
783 47 : eType = OFTTime;
784 47 : break;
785 355 : case GMLAS_FT_DATETIME:
786 355 : eType = OFTDateTime;
787 355 : break;
788 94 : case GMLAS_FT_BASE64BINARY:
789 : case GMLAS_FT_HEXBINARY:
790 94 : eType = OFTBinary;
791 94 : break;
792 1767 : case GMLAS_FT_ANYURI:
793 1767 : eType = OFTString;
794 1767 : break;
795 498 : case GMLAS_FT_ANYTYPE:
796 498 : eType = OFTString;
797 498 : break;
798 702 : case GMLAS_FT_ANYSIMPLETYPE:
799 702 : eType = OFTString;
800 702 : break;
801 364 : case GMLAS_FT_GEOMETRY:
802 : {
803 : // Create a geometry field
804 : OGRGeomFieldDefn oGeomFieldDefn(osOGRFieldName,
805 728 : oField.GetGeomType());
806 364 : m_poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
807 :
808 : const int iOGRGeomIdx =
809 364 : m_poFeatureDefn->GetGeomFieldCount() - 1;
810 364 : if (!oField.GetXPath().empty())
811 : {
812 333 : m_oMapFieldXPathToOGRGeomFieldIdx[oField.GetXPath()] =
813 : iOGRGeomIdx;
814 : }
815 : else
816 : {
817 : const std::vector<CPLString> &aoXPaths =
818 31 : oField.GetAlternateXPaths();
819 668 : for (size_t j = 0; j < aoXPaths.size(); j++)
820 : {
821 637 : m_oMapFieldXPathToOGRGeomFieldIdx[aoXPaths[j]] =
822 : iOGRGeomIdx;
823 : }
824 : }
825 :
826 364 : m_oMapOGRGeomFieldIdxtoFCFieldIdx[iOGRGeomIdx] = i;
827 :
828 : // Suffix the regular non-geometry field
829 364 : osOGRFieldName += szXML_SUFFIX;
830 364 : eType = OFTString;
831 364 : break;
832 : }
833 0 : default:
834 0 : CPLError(CE_Warning, CPLE_AppDefined,
835 0 : "Unhandled type in enum: %d", oField.GetType());
836 0 : break;
837 : }
838 :
839 174130 : if (oField.GetType() == GMLAS_FT_GEOMETRY && !bIncludeGeometryXML)
840 : {
841 332 : continue;
842 : }
843 :
844 173798 : if (oField.IsArray())
845 : {
846 3611 : switch (eType)
847 : {
848 3097 : case OFTString:
849 3097 : eType = OFTStringList;
850 3097 : break;
851 282 : case OFTInteger:
852 282 : eType = OFTIntegerList;
853 282 : break;
854 94 : case OFTInteger64:
855 94 : eType = OFTInteger64List;
856 94 : break;
857 138 : case OFTReal:
858 138 : eType = OFTRealList;
859 138 : break;
860 0 : default:
861 0 : CPLError(CE_Warning, CPLE_AppDefined,
862 : "Unhandled type in enum: %d", eType);
863 0 : break;
864 : }
865 : }
866 347596 : OGRFieldDefn oFieldDefn(osOGRFieldName, eType);
867 173798 : oFieldDefn.SetSubType(eSubType);
868 173798 : if (oField.IsNotNullable())
869 35922 : oFieldDefn.SetNullable(false);
870 347596 : CPLString osDefaultOrFixed = oField.GetDefaultValue();
871 173798 : if (osDefaultOrFixed.empty())
872 173577 : osDefaultOrFixed = oField.GetFixedValue();
873 173798 : if (!osDefaultOrFixed.empty())
874 : {
875 636 : char *pszEscaped = CPLEscapeString(osDefaultOrFixed, -1, CPLES_SQL);
876 636 : oFieldDefn.SetDefault(
877 1272 : (CPLString("'") + pszEscaped + CPLString("'")).c_str());
878 636 : CPLFree(pszEscaped);
879 : }
880 173798 : oFieldDefn.SetWidth(oField.GetWidth());
881 173798 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
882 :
883 173798 : const int iOGRIdx = m_poFeatureDefn->GetFieldCount() - 1;
884 173798 : if (!oField.GetXPath().empty())
885 : {
886 173738 : m_oMapFieldXPathToOGRFieldIdx[oField.GetXPath()] = iOGRIdx;
887 : }
888 : else
889 : {
890 : const std::vector<CPLString> &aoXPaths =
891 60 : oField.GetAlternateXPaths();
892 162 : for (size_t j = 0; j < aoXPaths.size(); j++)
893 : {
894 102 : m_oMapFieldXPathToOGRFieldIdx[aoXPaths[j]] = iOGRIdx;
895 : }
896 : }
897 :
898 173798 : m_oMapOGRFieldIdxtoFCFieldIdx[iOGRIdx] = i;
899 :
900 : // Create field to receive resolved xlink:href content, if needed
901 173798 : if (oField.GetXPath().find(szAT_XLINK_HREF) != std::string::npos &&
902 173810 : m_poDS->GetConf().m_oXLinkResolution.m_bDefaultResolutionEnabled &&
903 12 : m_poDS->GetConf().m_oXLinkResolution.m_eDefaultResolutionMode ==
904 : GMLASXLinkResolutionConf::RawContent)
905 : {
906 24 : CPLString osRawContentFieldname(osOGRFieldName);
907 12 : size_t nPos = osRawContentFieldname.find(szHREF_SUFFIX);
908 12 : if (nPos != std::string::npos)
909 12 : osRawContentFieldname.resize(nPos);
910 12 : osRawContentFieldname += szRAW_CONTENT_SUFFIX;
911 12 : OGRFieldDefn oFieldDefnRaw(osRawContentFieldname, OFTString);
912 12 : m_poFeatureDefn->AddFieldDefn(&oFieldDefnRaw);
913 :
914 : m_oMapFieldXPathToOGRFieldIdx
915 24 : [GMLASField::MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
916 24 : oField.GetXPath())] = m_poFeatureDefn->GetFieldCount() - 1;
917 : }
918 :
919 173798 : CPL_IGNORE_RET_VAL(osOGRFieldName);
920 : }
921 :
922 6407 : CreateCompoundFoldedMappings();
923 : }
924 :
925 : /************************************************************************/
926 : /* CreateCompoundFoldedMappings() */
927 : /************************************************************************/
928 :
929 : // In the case we have nested elements but we managed to fold into top
930 : // level class, then register intermediate paths so they are not reported
931 : // as unexpected in debug traces
932 6408 : void OGRGMLASLayer::CreateCompoundFoldedMappings()
933 : {
934 12816 : CPLString oFCXPath(m_oFC.GetXPath());
935 6408 : if (m_oFC.IsRepeatedSequence())
936 : {
937 313 : size_t iPosExtra = oFCXPath.find(szEXTRA_SUFFIX);
938 313 : if (iPosExtra != std::string::npos)
939 : {
940 218 : oFCXPath.resize(iPosExtra);
941 : }
942 : }
943 :
944 6408 : const std::vector<GMLASField> &oFields = m_oFC.GetFields();
945 194071 : for (size_t i = 0; i < oFields.size(); i++)
946 : {
947 375326 : std::vector<CPLString> aoXPaths = oFields[i].GetAlternateXPaths();
948 187663 : if (aoXPaths.empty())
949 187580 : aoXPaths.push_back(oFields[i].GetXPath());
950 375978 : for (size_t j = 0; j < aoXPaths.size(); j++)
951 : {
952 188315 : if (aoXPaths[j].size() > oFCXPath.size())
953 : {
954 : // Split on both '/' and '@'
955 375356 : char **papszTokens = CSLTokenizeString2(
956 187678 : aoXPaths[j].c_str() + oFCXPath.size() + 1, "/@", 0);
957 375356 : CPLString osSubXPath = oFCXPath;
958 590935 : for (int k = 0;
959 590935 : papszTokens[k] != nullptr && papszTokens[k + 1] != nullptr;
960 : k++)
961 : {
962 403257 : osSubXPath += "/";
963 403257 : osSubXPath += papszTokens[k];
964 403257 : if (m_oMapFieldXPathToOGRFieldIdx.find(osSubXPath) ==
965 806514 : m_oMapFieldXPathToOGRFieldIdx.end())
966 : {
967 22276 : m_oMapFieldXPathToOGRFieldIdx[osSubXPath] =
968 : IDX_COMPOUND_FOLDED;
969 : }
970 : }
971 187678 : CSLDestroy(papszTokens);
972 : }
973 : }
974 : }
975 6408 : }
976 :
977 : /************************************************************************/
978 : /* ~OGRGMLASLayer() */
979 : /************************************************************************/
980 :
981 30548 : OGRGMLASLayer::~OGRGMLASLayer()
982 : {
983 15274 : m_poFeatureDefn->Release();
984 30548 : }
985 :
986 : /************************************************************************/
987 : /* DeleteTargetIndex() */
988 : /************************************************************************/
989 :
990 4 : static void DeleteTargetIndex(std::map<CPLString, int> &oMap, int nIdx)
991 : {
992 4 : bool bIterToRemoveValid = false;
993 4 : std::map<CPLString, int>::iterator oIterToRemove;
994 4 : std::map<CPLString, int>::iterator oIter = oMap.begin();
995 26 : for (; oIter != oMap.end(); ++oIter)
996 : {
997 22 : if (oIter->second > nIdx)
998 10 : oIter->second--;
999 12 : else if (oIter->second == nIdx)
1000 : {
1001 4 : bIterToRemoveValid = true;
1002 4 : oIterToRemove = oIter;
1003 : }
1004 : }
1005 4 : if (bIterToRemoveValid)
1006 4 : oMap.erase(oIterToRemove);
1007 4 : }
1008 :
1009 : /************************************************************************/
1010 : /* RemoveField() */
1011 : /************************************************************************/
1012 :
1013 4 : bool OGRGMLASLayer::RemoveField(int nIdx)
1014 : {
1015 4 : if (nIdx == m_nIDFieldIdx || nIdx == m_nParentIDFieldIdx)
1016 0 : return false;
1017 :
1018 4 : m_poFeatureDefn->DeleteFieldDefn(nIdx);
1019 :
1020 : // Refresh maps
1021 4 : DeleteTargetIndex(m_oMapFieldXPathToOGRFieldIdx, nIdx);
1022 :
1023 : {
1024 8 : std::map<int, int> oMapOGRFieldIdxtoFCFieldIdx;
1025 26 : for (const auto &oIter : m_oMapOGRFieldIdxtoFCFieldIdx)
1026 : {
1027 22 : if (oIter.first < nIdx)
1028 8 : oMapOGRFieldIdxtoFCFieldIdx[oIter.first] = oIter.second;
1029 14 : else if (oIter.first > nIdx)
1030 10 : oMapOGRFieldIdxtoFCFieldIdx[oIter.first - 1] = oIter.second;
1031 : }
1032 4 : m_oMapOGRFieldIdxtoFCFieldIdx = std::move(oMapOGRFieldIdxtoFCFieldIdx);
1033 : }
1034 :
1035 4 : OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();
1036 : OGRFeature *poFeature;
1037 4 : poFieldsMetadataLayer->ResetReading();
1038 27 : while ((poFeature = poFieldsMetadataLayer->GetNextFeature()) != nullptr)
1039 : {
1040 44 : if (strcmp(poFeature->GetFieldAsString(szLAYER_NAME), GetName()) == 0 &&
1041 18 : poFeature->GetFieldAsInteger(szFIELD_INDEX) == nIdx)
1042 : {
1043 3 : poFeature->SetField(szFIELD_INDEX, -1);
1044 3 : CPL_IGNORE_RET_VAL(poFieldsMetadataLayer->SetFeature(poFeature));
1045 3 : delete poFeature;
1046 3 : break;
1047 : }
1048 23 : delete poFeature;
1049 : }
1050 4 : poFieldsMetadataLayer->ResetReading();
1051 :
1052 4 : return true;
1053 : }
1054 :
1055 : /************************************************************************/
1056 : /* InsertTargetIndex() */
1057 : /************************************************************************/
1058 :
1059 22 : static void InsertTargetIndex(std::map<CPLString, int> &oMap, int nIdx)
1060 : {
1061 271 : for (auto &oIter : oMap)
1062 : {
1063 249 : if (oIter.second >= nIdx)
1064 43 : oIter.second++;
1065 : }
1066 22 : }
1067 :
1068 : /************************************************************************/
1069 : /* InsertNewField() */
1070 : /************************************************************************/
1071 :
1072 22 : void OGRGMLASLayer::InsertNewField(int nInsertPos,
1073 : const OGRFieldDefn &oFieldDefn,
1074 : const CPLString &osXPath)
1075 : {
1076 22 : CPLAssert(nInsertPos >= 0 &&
1077 : nInsertPos <= m_poFeatureDefn->GetFieldCount());
1078 22 : m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
1079 22 : int *panMap = new int[m_poFeatureDefn->GetFieldCount()];
1080 204 : for (int i = 0; i < nInsertPos; ++i)
1081 : {
1082 182 : panMap[i] = i;
1083 : }
1084 22 : panMap[nInsertPos] = m_poFeatureDefn->GetFieldCount() - 1;
1085 65 : for (int i = nInsertPos + 1; i < m_poFeatureDefn->GetFieldCount(); ++i)
1086 : {
1087 43 : panMap[i] = i - 1;
1088 : }
1089 22 : m_poFeatureDefn->ReorderFieldDefns(panMap);
1090 22 : delete[] panMap;
1091 :
1092 : // Refresh maps
1093 22 : InsertTargetIndex(m_oMapFieldXPathToOGRFieldIdx, nInsertPos);
1094 22 : m_oMapFieldXPathToOGRFieldIdx[osXPath] = nInsertPos;
1095 :
1096 : {
1097 44 : std::map<int, int> oMapOGRFieldIdxtoFCFieldIdx;
1098 152 : for (const auto &oIter : m_oMapOGRFieldIdxtoFCFieldIdx)
1099 : {
1100 130 : if (oIter.first < nInsertPos)
1101 87 : oMapOGRFieldIdxtoFCFieldIdx[oIter.first] = oIter.second;
1102 : else
1103 43 : oMapOGRFieldIdxtoFCFieldIdx[oIter.first + 1] = oIter.second;
1104 : }
1105 22 : m_oMapOGRFieldIdxtoFCFieldIdx = std::move(oMapOGRFieldIdxtoFCFieldIdx);
1106 : }
1107 :
1108 22 : OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();
1109 : OGRFeature *poFeature;
1110 22 : poFieldsMetadataLayer->ResetReading();
1111 165 : while ((poFeature = poFieldsMetadataLayer->GetNextFeature()) != nullptr)
1112 : {
1113 143 : if (strcmp(poFeature->GetFieldAsString(szLAYER_NAME), GetName()) == 0)
1114 : {
1115 131 : int nFieldIndex = poFeature->GetFieldAsInteger(szFIELD_INDEX);
1116 131 : if (nFieldIndex >= nInsertPos && nFieldIndex < INT_MAX)
1117 : {
1118 43 : poFeature->SetField(szFIELD_INDEX, nFieldIndex + 1);
1119 43 : CPL_IGNORE_RET_VAL(
1120 43 : poFieldsMetadataLayer->SetFeature(poFeature));
1121 : }
1122 : }
1123 143 : delete poFeature;
1124 : }
1125 22 : poFieldsMetadataLayer->ResetReading();
1126 22 : }
1127 :
1128 : /************************************************************************/
1129 : /* GetOGRFieldIndexFromXPath() */
1130 : /************************************************************************/
1131 :
1132 1152680 : int OGRGMLASLayer::GetOGRFieldIndexFromXPath(const CPLString &osXPath) const
1133 : {
1134 1152680 : const auto oIter = m_oMapFieldXPathToOGRFieldIdx.find(osXPath);
1135 1152680 : if (oIter == m_oMapFieldXPathToOGRFieldIdx.end())
1136 932221 : return -1;
1137 220455 : return oIter->second;
1138 : }
1139 :
1140 : /************************************************************************/
1141 : /* GetXPathFromOGRFieldIndex() */
1142 : /************************************************************************/
1143 :
1144 14 : CPLString OGRGMLASLayer::GetXPathFromOGRFieldIndex(int nIdx) const
1145 : {
1146 14 : const int nFCIdx = GetFCFieldIndexFromOGRFieldIdx(nIdx);
1147 14 : if (nFCIdx >= 0)
1148 10 : return m_oFC.GetFields()[nFCIdx].GetXPath();
1149 :
1150 31 : for (const auto &oIter : m_oMapFieldXPathToOGRFieldIdx)
1151 : {
1152 28 : if (oIter.second == nIdx)
1153 1 : return oIter.first;
1154 : }
1155 3 : return CPLString();
1156 : }
1157 :
1158 : /************************************************************************/
1159 : /* GetOGRGeomFieldIndexFromXPath() */
1160 : /************************************************************************/
1161 :
1162 188883 : int OGRGMLASLayer::GetOGRGeomFieldIndexFromXPath(const CPLString &osXPath) const
1163 : {
1164 188883 : const auto oIter = m_oMapFieldXPathToOGRGeomFieldIdx.find(osXPath);
1165 188883 : if (oIter == m_oMapFieldXPathToOGRGeomFieldIdx.end())
1166 188439 : return -1;
1167 444 : return oIter->second;
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* GetFCFieldIndexFromOGRFieldIdx() */
1172 : /************************************************************************/
1173 :
1174 5410100 : int OGRGMLASLayer::GetFCFieldIndexFromOGRFieldIdx(int iOGRFieldIdx) const
1175 : {
1176 5410100 : const auto oIter = m_oMapOGRFieldIdxtoFCFieldIdx.find(iOGRFieldIdx);
1177 5410100 : if (oIter == m_oMapOGRFieldIdxtoFCFieldIdx.end())
1178 141941 : return -1;
1179 5268160 : return oIter->second;
1180 : }
1181 :
1182 : /************************************************************************/
1183 : /* GetFCFieldIndexFromXPath() */
1184 : /************************************************************************/
1185 :
1186 746 : int OGRGMLASLayer::GetFCFieldIndexFromXPath(const CPLString &osXPath) const
1187 : {
1188 746 : const auto oIter = m_oMapFieldXPathToFCFieldIdx.find(osXPath);
1189 746 : if (oIter == m_oMapFieldXPathToFCFieldIdx.end())
1190 251 : return -1;
1191 495 : return oIter->second;
1192 : }
1193 :
1194 : /************************************************************************/
1195 : /* GetFCFieldIndexFromOGRGeomFieldIdx() */
1196 : /************************************************************************/
1197 :
1198 368 : int OGRGMLASLayer::GetFCFieldIndexFromOGRGeomFieldIdx(
1199 : int iOGRGeomFieldIdx) const
1200 : {
1201 368 : const auto oIter = m_oMapOGRGeomFieldIdxtoFCFieldIdx.find(iOGRGeomFieldIdx);
1202 368 : if (oIter == m_oMapOGRGeomFieldIdxtoFCFieldIdx.end())
1203 0 : return -1;
1204 368 : return oIter->second;
1205 : }
1206 :
1207 : /************************************************************************/
1208 : /* GetXPathOfFieldLinkForAttrToOtherLayer() */
1209 : /************************************************************************/
1210 :
1211 9 : CPLString OGRGMLASLayer::GetXPathOfFieldLinkForAttrToOtherLayer(
1212 : const CPLString &osFieldName, const CPLString &osTargetLayerXPath)
1213 : {
1214 9 : const int nOGRFieldIdx = GetLayerDefn()->GetFieldIndex(osFieldName);
1215 9 : CPLAssert(nOGRFieldIdx >= 0);
1216 9 : const int nFCFieldIdx = GetFCFieldIndexFromOGRFieldIdx(nOGRFieldIdx);
1217 9 : CPLAssert(nFCFieldIdx >= 0);
1218 18 : CPLString osXPath(m_oFC.GetFields()[nFCFieldIdx].GetXPath());
1219 9 : size_t nPos = osXPath.find(szAT_XLINK_HREF);
1220 9 : CPLAssert(nPos != std::string::npos);
1221 9 : CPLAssert(nPos + strlen(szAT_XLINK_HREF) == osXPath.size());
1222 18 : CPLString osTargetFieldXPath(osXPath.substr(0, nPos) + osTargetLayerXPath);
1223 18 : return osTargetFieldXPath;
1224 : }
1225 :
1226 : /************************************************************************/
1227 : /* LaunderFieldName() */
1228 : /************************************************************************/
1229 :
1230 3 : CPLString OGRGMLASLayer::LaunderFieldName(const CPLString &osFieldName)
1231 : {
1232 3 : int nCounter = 1;
1233 3 : CPLString osLaunderedName(osFieldName);
1234 3 : while (m_poFeatureDefn->GetFieldIndex(osLaunderedName) >= 0)
1235 : {
1236 0 : nCounter++;
1237 0 : osLaunderedName = osFieldName + CPLSPrintf("%d", nCounter);
1238 : }
1239 :
1240 3 : const int nIdentifierMaxLength = m_poDS->GetConf().m_nIdentifierMaxLength;
1241 6 : if (nIdentifierMaxLength >= MIN_VALUE_OF_MAX_IDENTIFIER_LENGTH &&
1242 3 : osLaunderedName.size() > static_cast<size_t>(nIdentifierMaxLength))
1243 : {
1244 : osLaunderedName =
1245 1 : OGRGMLASTruncateIdentifier(osLaunderedName, nIdentifierMaxLength);
1246 : }
1247 :
1248 3 : if (m_poDS->GetConf().m_bPGIdentifierLaundering)
1249 : {
1250 : char *pszLaundered =
1251 3 : OGRPGCommonLaunderName(osLaunderedName, "GMLAS", false);
1252 3 : osLaunderedName = pszLaundered;
1253 3 : CPLFree(pszLaundered);
1254 : }
1255 :
1256 3 : if (m_poFeatureDefn->GetFieldIndex(osLaunderedName) >= 0)
1257 : {
1258 0 : nCounter = 1;
1259 0 : std::string osCandidate;
1260 0 : do
1261 : {
1262 0 : nCounter++;
1263 0 : osCandidate = OGRGMLASAddSerialNumber(
1264 0 : osLaunderedName, nCounter, nCounter + 1, nIdentifierMaxLength);
1265 0 : } while (nCounter < 100 &&
1266 0 : m_poFeatureDefn->GetFieldIndex(osCandidate.c_str()) >= 0);
1267 0 : osLaunderedName = std::move(osCandidate);
1268 : }
1269 :
1270 3 : return osLaunderedName;
1271 : }
1272 :
1273 : /************************************************************************/
1274 : /* CreateLinkForAttrToOtherLayer() */
1275 : /************************************************************************/
1276 :
1277 : /* Create a new field to contain the PKID of the feature pointed by this */
1278 : /* osFieldName (a xlink:href attribute), when it is an internal link to */
1279 : /* another layer whose xpath is given by osTargetLayerXPath */
1280 :
1281 4 : CPLString OGRGMLASLayer::CreateLinkForAttrToOtherLayer(
1282 : const CPLString &osFieldName, const CPLString &osTargetLayerXPath)
1283 : {
1284 : CPLString osTargetFieldXPath =
1285 8 : GetXPathOfFieldLinkForAttrToOtherLayer(osFieldName, osTargetLayerXPath);
1286 : const int nExistingTgtOGRFieldIdx =
1287 4 : GetOGRFieldIndexFromXPath(osTargetFieldXPath);
1288 4 : if (nExistingTgtOGRFieldIdx >= 0)
1289 : {
1290 1 : return GetLayerDefn()
1291 1 : ->GetFieldDefn(nExistingTgtOGRFieldIdx)
1292 1 : ->GetNameRef();
1293 : }
1294 :
1295 3 : const int nOGRFieldIdx = GetLayerDefn()->GetFieldIndex(osFieldName);
1296 3 : CPLAssert(nOGRFieldIdx >= 0);
1297 3 : const int nFCFieldIdx = GetFCFieldIndexFromOGRFieldIdx(nOGRFieldIdx);
1298 3 : CPLAssert(nFCFieldIdx >= 0);
1299 6 : CPLString osXPath(m_oFC.GetFields()[nFCFieldIdx].GetXPath());
1300 3 : size_t nPos = osXPath.find(szAT_XLINK_HREF);
1301 6 : CPLString osXPathStart(osXPath.substr(0, nPos));
1302 :
1303 : // Find at which position to insert the new field in the layer definition
1304 : // (we could happen at the end, but it will be nicer to insert close to
1305 : // the href field)
1306 3 : int nInsertPos = -1;
1307 14 : for (int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++)
1308 : {
1309 14 : if (GetXPathFromOGRFieldIndex(i).find(osXPathStart) == 0)
1310 : {
1311 4 : nInsertPos = i + 1;
1312 : }
1313 10 : else if (nInsertPos >= 0)
1314 3 : break;
1315 : }
1316 :
1317 6 : CPLString osNewFieldName(osFieldName);
1318 3 : nPos = osFieldName.find(szHREF_SUFFIX);
1319 3 : if (nPos != std::string::npos)
1320 : {
1321 3 : osNewFieldName.resize(nPos);
1322 : }
1323 3 : osNewFieldName += "_";
1324 3 : OGRGMLASLayer *poTargetLayer = m_poDS->GetLayerByXPath(osTargetLayerXPath);
1325 3 : CPLAssert(poTargetLayer);
1326 3 : osNewFieldName += poTargetLayer->GetName();
1327 3 : osNewFieldName += "_pkid";
1328 3 : osNewFieldName = LaunderFieldName(osNewFieldName);
1329 6 : OGRFieldDefn oFieldDefn(osNewFieldName, OFTString);
1330 3 : InsertNewField(nInsertPos, oFieldDefn, osTargetFieldXPath);
1331 :
1332 3 : OGRLayer *poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();
1333 3 : OGRLayer *poRelationshipsLayer = m_poDS->GetRelationshipsLayer();
1334 :
1335 : // Find a relevant location of the field metadata layer into which to
1336 : // insert the new feature (same as above, we could potentially insert just
1337 : // at the end)
1338 3 : GIntBig nFieldsMetadataIdxPos = -1;
1339 3 : poFieldsMetadataLayer->ResetReading();
1340 : OGRFeature *poFeature;
1341 11 : while ((poFeature = poFieldsMetadataLayer->GetNextFeature()) != nullptr)
1342 : {
1343 11 : if (strcmp(poFeature->GetFieldAsString(szLAYER_NAME), GetName()) == 0)
1344 : {
1345 11 : if (poFeature->GetFieldAsInteger(szFIELD_INDEX) > nInsertPos)
1346 : {
1347 3 : delete poFeature;
1348 3 : break;
1349 : }
1350 8 : nFieldsMetadataIdxPos = poFeature->GetFID() + 1;
1351 : }
1352 0 : else if (nFieldsMetadataIdxPos >= 0)
1353 : {
1354 0 : delete poFeature;
1355 0 : break;
1356 : }
1357 8 : delete poFeature;
1358 : }
1359 3 : poFieldsMetadataLayer->ResetReading();
1360 :
1361 : // Move down all features beyond that insertion point
1362 24 : for (GIntBig nFID = poFieldsMetadataLayer->GetFeatureCount() - 1;
1363 24 : nFID >= nFieldsMetadataIdxPos; nFID--)
1364 : {
1365 21 : poFeature = poFieldsMetadataLayer->GetFeature(nFID);
1366 21 : if (poFeature)
1367 : {
1368 21 : poFeature->SetFID(nFID + 1);
1369 21 : CPL_IGNORE_RET_VAL(poFieldsMetadataLayer->SetFeature(poFeature));
1370 21 : delete poFeature;
1371 : }
1372 : }
1373 3 : if (nFieldsMetadataIdxPos >= 0)
1374 : {
1375 3 : CPL_IGNORE_RET_VAL(
1376 3 : poFieldsMetadataLayer->DeleteFeature(nFieldsMetadataIdxPos));
1377 : }
1378 :
1379 : // Register field in _ogr_fields_metadata
1380 : OGRFeature *poFieldDescFeature =
1381 3 : new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
1382 3 : poFieldDescFeature->SetField(szLAYER_NAME, GetName());
1383 3 : poFieldDescFeature->SetField(szFIELD_INDEX, nInsertPos);
1384 3 : poFieldDescFeature->SetField(szFIELD_XPATH, osTargetFieldXPath);
1385 3 : poFieldDescFeature->SetField(szFIELD_NAME, oFieldDefn.GetNameRef());
1386 3 : poFieldDescFeature->SetField(szFIELD_TYPE, szXS_STRING);
1387 3 : poFieldDescFeature->SetField(szFIELD_IS_LIST, 0);
1388 3 : poFieldDescFeature->SetField(szFIELD_MIN_OCCURS, 0);
1389 3 : poFieldDescFeature->SetField(szFIELD_MAX_OCCURS, 1);
1390 3 : poFieldDescFeature->SetField(szFIELD_CATEGORY,
1391 : szPATH_TO_CHILD_ELEMENT_WITH_LINK);
1392 3 : poFieldDescFeature->SetField(szFIELD_RELATED_LAYER,
1393 : poTargetLayer->GetName());
1394 3 : if (nFieldsMetadataIdxPos >= 0)
1395 3 : poFieldDescFeature->SetFID(nFieldsMetadataIdxPos);
1396 3 : CPL_IGNORE_RET_VAL(
1397 3 : poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
1398 3 : delete poFieldDescFeature;
1399 :
1400 : // Register relationship in _ogr_layer_relationships
1401 : OGRFeature *poRelationshipsFeature =
1402 3 : new OGRFeature(poRelationshipsLayer->GetLayerDefn());
1403 3 : poRelationshipsFeature->SetField(szPARENT_LAYER, GetName());
1404 3 : poRelationshipsFeature->SetField(
1405 : szPARENT_PKID,
1406 3 : GetLayerDefn()->GetFieldDefn(GetIDFieldIdx())->GetNameRef());
1407 3 : poRelationshipsFeature->SetField(szPARENT_ELEMENT_NAME, osNewFieldName);
1408 3 : poRelationshipsFeature->SetField(szCHILD_LAYER, poTargetLayer->GetName());
1409 3 : poRelationshipsFeature->SetField(
1410 3 : szCHILD_PKID, poTargetLayer->GetLayerDefn()
1411 3 : ->GetFieldDefn(poTargetLayer->GetIDFieldIdx())
1412 : ->GetNameRef());
1413 3 : CPL_IGNORE_RET_VAL(
1414 3 : poRelationshipsLayer->CreateFeature(poRelationshipsFeature));
1415 3 : delete poRelationshipsFeature;
1416 :
1417 3 : return osNewFieldName;
1418 : }
1419 :
1420 : /************************************************************************/
1421 : /* GetLayerDefn() */
1422 : /************************************************************************/
1423 :
1424 255296 : OGRFeatureDefn *OGRGMLASLayer::GetLayerDefn()
1425 : {
1426 255296 : if (!m_bLayerDefnFinalized && m_poDS->IsLayerInitFinished())
1427 : {
1428 : // If we haven't yet determined the SRS of geometry columns, do it now
1429 15 : m_bLayerDefnFinalized = true;
1430 15 : if (m_poFeatureDefn->GetGeomFieldCount() > 0 ||
1431 20 : m_poDS->GetConf().m_oXLinkResolution.m_bResolveInternalXLinks ||
1432 5 : !m_poDS->GetConf().m_oXLinkResolution.m_aoURLSpecificRules.empty())
1433 : {
1434 10 : if (m_poReader == nullptr)
1435 : {
1436 10 : InitReader();
1437 : // Avoid keeping too many file descriptor opened
1438 10 : if (m_fpGML != nullptr)
1439 9 : m_poDS->PushUnusedGMLFilePointer(m_fpGML);
1440 10 : m_poReader.reset();
1441 : }
1442 : }
1443 : }
1444 255296 : return m_poFeatureDefn;
1445 : }
1446 :
1447 : /************************************************************************/
1448 : /* ResetReading() */
1449 : /************************************************************************/
1450 :
1451 2128 : void OGRGMLASLayer::ResetReading()
1452 : {
1453 2128 : m_poReader.reset();
1454 2128 : m_bEOF = false;
1455 2128 : }
1456 :
1457 : /************************************************************************/
1458 : /* InitReader() */
1459 : /************************************************************************/
1460 :
1461 1110 : bool OGRGMLASLayer::InitReader()
1462 : {
1463 1110 : CPLAssert(m_poReader == nullptr);
1464 :
1465 1110 : m_bLayerDefnFinalized = true;
1466 1110 : m_poReader.reset(m_poDS->CreateReader(m_fpGML));
1467 1110 : if (m_poReader != nullptr)
1468 : {
1469 1109 : m_poReader->SetLayerOfInterest(this);
1470 1109 : return true;
1471 : }
1472 1 : return false;
1473 : }
1474 :
1475 : /************************************************************************/
1476 : /* GetNextRawFeature() */
1477 : /************************************************************************/
1478 :
1479 2840 : OGRFeature *OGRGMLASLayer::GetNextRawFeature()
1480 : {
1481 2840 : if (m_poReader == nullptr && !InitReader())
1482 0 : return nullptr;
1483 :
1484 2840 : return m_poReader->GetNextFeature();
1485 : }
1486 :
1487 : /************************************************************************/
1488 : /* EvaluateFilter() */
1489 : /************************************************************************/
1490 :
1491 2822 : bool OGRGMLASLayer::EvaluateFilter(OGRFeature *poFeature)
1492 : {
1493 2822 : return (m_poFilterGeom == nullptr ||
1494 5644 : FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
1495 5644 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature));
1496 : }
1497 :
1498 : /************************************************************************/
1499 : /* GetNextFeature() */
1500 : /************************************************************************/
1501 :
1502 2579 : OGRFeature *OGRGMLASLayer::GetNextFeature()
1503 : {
1504 2579 : if (m_bEOF)
1505 27 : return nullptr;
1506 :
1507 : while (true)
1508 : {
1509 2840 : OGRFeature *poFeature = GetNextRawFeature();
1510 2840 : if (poFeature == nullptr)
1511 : {
1512 : // Avoid keeping too many file descriptor opened
1513 798 : if (m_fpGML != nullptr)
1514 798 : m_poDS->PushUnusedGMLFilePointer(m_fpGML);
1515 798 : m_poReader.reset();
1516 798 : m_bEOF = true;
1517 798 : return nullptr;
1518 : }
1519 :
1520 2042 : if (EvaluateFilter(poFeature))
1521 : {
1522 1754 : return poFeature;
1523 : }
1524 :
1525 288 : delete poFeature;
1526 288 : }
1527 : }
|