Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GML Reader 4 : * Purpose: Implementation of GML GFS template management 5 : * Author: Alessandro Furieri, a.furitier@lqt.it 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2011, Alessandro Furieri 9 : * 10 : * SPDX-License-Identifier: MIT 11 : * 12 : ****************************************************************************** 13 : * Contributor: Alessandro Furieri, a.furieri@lqt.it 14 : * Developed for Faunalia ( http://www.faunalia.it) with funding from 15 : * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE 16 : * 17 : ****************************************************************************/ 18 : 19 : #include "cpl_port.h" 20 : #include "gmlreaderp.h" 21 : #include "ogr_gml.h" 22 : 23 : #include <cstddef> 24 : 25 : #include "cpl_conv.h" 26 : #include "cpl_minixml.h" 27 : #include "gmlreader.h" 28 : #include "ogr_core.h" 29 : 30 : /************************************************************************/ 31 : /* GFSTemplateItem */ 32 : /************************************************************************/ 33 : 34 : class GFSTemplateItem 35 : { 36 : private: 37 : char *m_pszName = nullptr; 38 : int n_nItemCount = 0; 39 : int n_nGeomCount = 0; 40 : GFSTemplateItem *pNext = nullptr; 41 : 42 : CPL_DISALLOW_COPY_ASSIGN(GFSTemplateItem) 43 : 44 : public: 45 : explicit GFSTemplateItem(const char *pszName); 46 : ~GFSTemplateItem(); 47 : 48 160 : const char *GetName() 49 : { 50 160 : return m_pszName; 51 : } 52 : 53 : void Update(int b_has_geom); 54 : 55 5 : int GetCount() 56 : { 57 5 : return n_nItemCount; 58 : } 59 : 60 5 : int GetGeomCount() 61 : { 62 5 : return n_nGeomCount; 63 : } 64 : 65 4 : void SetNext(GFSTemplateItem *pN) 66 : { 67 4 : pNext = pN; 68 4 : } 69 : 70 27 : GFSTemplateItem *GetNext() 71 : { 72 27 : return pNext; 73 : } 74 : }; 75 : 76 : /***************************************************/ 77 : /* gmlUpdateFeatureClasses() */ 78 : /***************************************************/ 79 : 80 3 : void gmlUpdateFeatureClasses(GFSTemplateList *pCC, GMLReader *pReader, 81 : int *pbSequentialLayers) 82 : { 83 : // Updating the FeatureClass list. 84 8 : for (int clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++) 85 : { 86 5 : GMLFeatureClass *poClass = pReader->GetClass(clIdx); 87 5 : if (poClass != nullptr) 88 5 : poClass->SetFeatureCount(0); 89 : } 90 3 : bool bValid = false; 91 3 : GFSTemplateItem *pItem = pCC->GetFirst(); 92 10 : while (pItem != nullptr) 93 : { 94 : // Updating Classes. 95 7 : GMLFeatureClass *poClass = pReader->GetClass(pItem->GetName()); 96 7 : if (poClass != nullptr) 97 : { 98 5 : poClass->SetFeatureCount(pItem->GetCount()); 99 10 : if (pItem->GetGeomCount() != 0 && 100 5 : poClass->GetGeometryPropertyCount() == 0) 101 10 : poClass->AddGeometryProperty( 102 5 : new GMLGeometryPropertyDefn("", "", wkbUnknown, -1, true)); 103 5 : bValid = true; 104 : } 105 7 : pItem = pItem->GetNext(); 106 : } 107 3 : if (bValid && pCC->HaveSequentialLayers()) 108 3 : *pbSequentialLayers = TRUE; 109 3 : } 110 : 111 : /***************************************************/ 112 : /* GMLReader::ReArrangeTemplateClasses() */ 113 : /***************************************************/ 114 : 115 3 : bool GMLReader::ReArrangeTemplateClasses(GFSTemplateList *pCC) 116 : { 117 : // Rearranging the final FeatureClass list [SEQUENTIAL]. 118 : // TODO(schwehr): Why the m_ for m_nSavedClassCount? Not a member. 119 3 : const int m_nSavedClassCount = GetClassCount(); 120 : 121 : // Saving the previous FeatureClass list. 122 : GMLFeatureClass **m_papoSavedClass = static_cast<GMLFeatureClass **>( 123 3 : CPLMalloc(sizeof(void *) * m_nSavedClassCount)); 124 : 125 8 : for (int clIdx = 0; clIdx < GetClassCount(); clIdx++) 126 : { 127 : // Transferring any previous FeatureClass. 128 5 : m_papoSavedClass[clIdx] = m_papoClass[clIdx]; 129 : } 130 : 131 : // Cleaning the previous FeatureClass list. 132 3 : SetClassListLocked(false); 133 3 : CPLFree(m_papoClass); 134 3 : m_nClassCount = 0; 135 3 : m_papoClass = nullptr; 136 : 137 3 : GFSTemplateItem *pItem = pCC->GetFirst(); 138 10 : while (pItem != nullptr) 139 : { 140 : // Re-inserting any required FeatureClassup 141 : // accordingly to actual SEQUENTIAL layout. 142 7 : GMLFeatureClass *poClass = nullptr; 143 13 : for (int iClass = 0; iClass < m_nSavedClassCount; iClass++) 144 : { 145 11 : GMLFeatureClass *poItem = m_papoSavedClass[iClass]; 146 11 : if (EQUAL(poItem->GetName(), pItem->GetName())) 147 : { 148 5 : poClass = poItem; 149 5 : break; 150 : } 151 : } 152 7 : if (poClass != nullptr) 153 : { 154 5 : if (poClass->GetFeatureCount() > 0) 155 5 : AddClass(poClass); 156 : } 157 7 : pItem = pItem->GetNext(); 158 : } 159 3 : SetClassListLocked(true); 160 : 161 : // Destroying the saved List and any unused FeatureClass. 162 8 : for (int iClass = 0; iClass < m_nSavedClassCount; iClass++) 163 : { 164 5 : bool bUnused = true; 165 5 : GMLFeatureClass *poClass = m_papoSavedClass[iClass]; 166 7 : for (int iClass2 = 0; iClass2 < m_nClassCount; iClass2++) 167 : { 168 7 : if (m_papoClass[iClass2] == poClass) 169 : { 170 5 : bUnused = false; 171 5 : break; 172 : } 173 : } 174 5 : if (bUnused) 175 0 : delete poClass; 176 : } 177 3 : CPLFree(m_papoSavedClass); 178 3 : return true; 179 : } 180 : 181 : /***************************************************/ 182 : /* GMLReader::PrescanForTemplate() */ 183 : /***************************************************/ 184 : 185 2 : bool GMLReader::PrescanForTemplate() 186 : { 187 : // Below logic is not ready for FeatureProperty/FeaturePropertyList 188 2 : if (ShouldLookForClassAtAnyLevel()) 189 2 : return true; 190 : 191 0 : GMLFeature *poFeature = nullptr; 192 0 : GFSTemplateList *pCC = new GFSTemplateList(); 193 : 194 : // Processing GML features. 195 0 : while ((poFeature = NextFeature()) != nullptr) 196 : { 197 0 : GMLFeatureClass *poClass = poFeature->GetClass(); 198 0 : const CPLXMLNode *const *papsGeomList = poFeature->GetGeometryList(); 199 0 : bool b_has_geom = false; 200 : 201 0 : if (papsGeomList != nullptr) 202 : { 203 0 : int i = 0; 204 0 : const CPLXMLNode *psNode = papsGeomList[i]; 205 0 : while (psNode != nullptr) 206 : { 207 0 : b_has_geom = true; 208 0 : i++; 209 0 : psNode = papsGeomList[i]; 210 : } 211 : } 212 0 : pCC->Update(poClass->GetElementName(), b_has_geom); 213 : 214 0 : delete poFeature; 215 : } 216 : 217 0 : gmlUpdateFeatureClasses(pCC, this, &m_nHasSequentialLayers); 218 0 : if (m_nHasSequentialLayers == TRUE) 219 0 : ReArrangeTemplateClasses(pCC); 220 0 : const int iCount = pCC->GetClassCount(); 221 0 : delete pCC; 222 0 : CleanupParser(); 223 0 : return iCount > 0; 224 : } 225 : 226 : /***************************************************/ 227 : /* GFSTemplateList() */ 228 : /***************************************************/ 229 : 230 3 : GFSTemplateList::GFSTemplateList() 231 3 : : m_bSequentialLayers(true), pFirst(nullptr), pLast(nullptr) 232 : { 233 3 : } 234 : 235 : /***************************************************/ 236 : /* GFSTemplateList() */ 237 : /***************************************************/ 238 : 239 6 : GFSTemplateList::~GFSTemplateList() 240 : { 241 3 : GFSTemplateItem *pItem = pFirst; 242 10 : while (pItem != nullptr) 243 : { 244 7 : GFSTemplateItem *pNext = pItem->GetNext(); 245 7 : delete pItem; 246 7 : pItem = pNext; 247 : } 248 3 : } 249 : 250 : /***************************************************/ 251 : /* GFSTemplateList::Insert() */ 252 : /***************************************************/ 253 : 254 7 : GFSTemplateItem *GFSTemplateList::Insert(const char *pszName) 255 : { 256 7 : GFSTemplateItem *pItem = new GFSTemplateItem(pszName); 257 : 258 : // Inserting into the linked list. 259 7 : if (pFirst == nullptr) 260 3 : pFirst = pItem; 261 7 : if (pLast != nullptr) 262 4 : pLast->SetNext(pItem); 263 7 : pLast = pItem; 264 7 : return pItem; 265 : } 266 : 267 : /***************************************************/ 268 : /* GFSTemplateList::Update() */ 269 : /***************************************************/ 270 : 271 139 : void GFSTemplateList::Update(const char *pszName, int bHasGeom) 272 : { 273 139 : GFSTemplateItem *pItem = nullptr; 274 : 275 139 : if (pFirst == nullptr) 276 : { 277 : // Empty List: first item. 278 3 : pItem = Insert(pszName); 279 3 : pItem->Update(bHasGeom); 280 3 : return; 281 : } 282 136 : if (EQUAL(pszName, pLast->GetName())) 283 : { 284 : // Continuing with the current Class Item. 285 132 : pLast->Update(bHasGeom); 286 132 : return; 287 : } 288 : 289 4 : pItem = pFirst; 290 10 : while (pItem != nullptr) 291 : { 292 6 : if (EQUAL(pszName, pItem->GetName())) 293 : { 294 : // Class Item previously declared: NOT SEQUENTIAL. 295 0 : m_bSequentialLayers = false; 296 0 : pItem->Update(bHasGeom); 297 0 : return; 298 : } 299 6 : pItem = pItem->GetNext(); 300 : } 301 : 302 : // Inserting a new Class Item. 303 4 : pItem = Insert(pszName); 304 4 : pItem->Update(bHasGeom); 305 : } 306 : 307 : /***************************************************/ 308 : /* GFSTemplateList::GetClassCount() */ 309 : /***************************************************/ 310 : 311 0 : int GFSTemplateList::GetClassCount() 312 : { 313 0 : int iCount = 0; 314 0 : GFSTemplateItem *pItem = pFirst; 315 0 : while (pItem != nullptr) 316 : { 317 0 : iCount++; 318 0 : pItem = pItem->GetNext(); 319 : } 320 : 321 0 : return iCount; 322 : } 323 : 324 : /***************************************************/ 325 : /* GFSTemplateItem() */ 326 : /***************************************************/ 327 : 328 7 : GFSTemplateItem::GFSTemplateItem(const char *pszName) 329 7 : : m_pszName(CPLStrdup(pszName)) 330 : { 331 7 : } 332 : 333 : /***************************************************/ 334 : /* ~GFSTemplateItem() */ 335 : /***************************************************/ 336 : 337 14 : GFSTemplateItem::~GFSTemplateItem() 338 : { 339 7 : CPLFree(m_pszName); 340 7 : } 341 : 342 : /***************************************************/ 343 : /* GFSTemplateItem::Update() */ 344 : /***************************************************/ 345 : 346 139 : void GFSTemplateItem::Update(int bHasGeom) 347 : { 348 139 : n_nItemCount++; 349 139 : if (bHasGeom == TRUE) 350 139 : n_nGeomCount++; 351 139 : }