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