LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gml - gfstemplate.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 110 143 76.9 %
Date: 2024-11-21 22:18:42 Functions: 15 16 93.8 %

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

Generated by: LCOV version 1.14