LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gml - gfstemplate.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 111 144 77.1 %
Date: 2024-05-07 17:03:27 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      21             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  *
      28             :  ******************************************************************************
      29             :  * Contributor: Alessandro Furieri, a.furieri@lqt.it
      30             :  * Developed for Faunalia ( http://www.faunalia.it) with funding from
      31             :  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
      32             :  *
      33             :  ****************************************************************************/
      34             : 
      35             : #include "cpl_port.h"
      36             : #include "gmlreaderp.h"
      37             : #include "ogr_gml.h"
      38             : 
      39             : #include <cstddef>
      40             : 
      41             : #include "cpl_conv.h"
      42             : #include "cpl_minixml.h"
      43             : #include "gmlreader.h"
      44             : #include "ogr_core.h"
      45             : 
      46             : /************************************************************************/
      47             : /*                        GFSTemplateItem                               */
      48             : /************************************************************************/
      49             : 
      50             : class GFSTemplateItem
      51             : {
      52             :   private:
      53             :     char *m_pszName;
      54             :     int n_nItemCount;
      55             :     int n_nGeomCount;
      56             :     GFSTemplateItem *pNext;
      57             : 
      58             :   public:
      59             :     explicit GFSTemplateItem(const char *pszName);
      60             :     ~GFSTemplateItem();
      61             : 
      62         158 :     const char *GetName()
      63             :     {
      64         158 :         return m_pszName;
      65             :     }
      66             : 
      67             :     void Update(int b_has_geom);
      68             : 
      69           4 :     int GetCount()
      70             :     {
      71           4 :         return n_nItemCount;
      72             :     }
      73             : 
      74           4 :     int GetGeomCount()
      75             :     {
      76           4 :         return n_nGeomCount;
      77             :     }
      78             : 
      79           4 :     void SetNext(GFSTemplateItem *pN)
      80             :     {
      81           4 :         pNext = pN;
      82           4 :     }
      83             : 
      84          24 :     GFSTemplateItem *GetNext()
      85             :     {
      86          24 :         return pNext;
      87             :     }
      88             : };
      89             : 
      90             : /***************************************************/
      91             : /*               gmlUpdateFeatureClasses()         */
      92             : /***************************************************/
      93             : 
      94           2 : void gmlUpdateFeatureClasses(GFSTemplateList *pCC, GMLReader *pReader,
      95             :                              int *pbSequentialLayers)
      96             : {
      97             :     // Updating the FeatureClass list.
      98           6 :     for (int clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++)
      99             :     {
     100           4 :         GMLFeatureClass *poClass = pReader->GetClass(clIdx);
     101           4 :         if (poClass != nullptr)
     102           4 :             poClass->SetFeatureCount(0);
     103             :     }
     104           2 :     bool bValid = false;
     105           2 :     GFSTemplateItem *pItem = pCC->GetFirst();
     106           8 :     while (pItem != nullptr)
     107             :     {
     108             :         // Updating Classes.
     109           6 :         GMLFeatureClass *poClass = pReader->GetClass(pItem->GetName());
     110           6 :         if (poClass != nullptr)
     111             :         {
     112           4 :             poClass->SetFeatureCount(pItem->GetCount());
     113           8 :             if (pItem->GetGeomCount() != 0 &&
     114           4 :                 poClass->GetGeometryPropertyCount() == 0)
     115           8 :                 poClass->AddGeometryProperty(
     116           4 :                     new GMLGeometryPropertyDefn("", "", wkbUnknown, -1, true));
     117           4 :             bValid = true;
     118             :         }
     119           6 :         pItem = pItem->GetNext();
     120             :     }
     121           2 :     if (bValid && pCC->HaveSequentialLayers())
     122           2 :         *pbSequentialLayers = TRUE;
     123           2 : }
     124             : 
     125             : /***************************************************/
     126             : /*       GMLReader::ReArrangeTemplateClasses()     */
     127             : /***************************************************/
     128             : 
     129           2 : bool GMLReader::ReArrangeTemplateClasses(GFSTemplateList *pCC)
     130             : {
     131             :     // Rearranging the final FeatureClass list [SEQUENTIAL].
     132             :     // TODO(schwehr): Why the m_ for m_nSavedClassCount?  Not a member.
     133           2 :     const int m_nSavedClassCount = GetClassCount();
     134             : 
     135             :     // Saving the previous FeatureClass list.
     136             :     GMLFeatureClass **m_papoSavedClass = static_cast<GMLFeatureClass **>(
     137           2 :         CPLMalloc(sizeof(void *) * m_nSavedClassCount));
     138             : 
     139           6 :     for (int clIdx = 0; clIdx < GetClassCount(); clIdx++)
     140             :     {
     141             :         // Transferring any previous FeatureClass.
     142           4 :         m_papoSavedClass[clIdx] = m_papoClass[clIdx];
     143             :     }
     144             : 
     145             :     // Cleaning the previous FeatureClass list.
     146           2 :     SetClassListLocked(false);
     147           2 :     CPLFree(m_papoClass);
     148           2 :     m_nClassCount = 0;
     149           2 :     m_papoClass = nullptr;
     150             : 
     151           2 :     GFSTemplateItem *pItem = pCC->GetFirst();
     152           8 :     while (pItem != nullptr)
     153             :     {
     154             :         // Re-inserting any required FeatureClassup
     155             :         // accordingly to actual SEQUENTIAL layout.
     156           6 :         GMLFeatureClass *poClass = nullptr;
     157          12 :         for (int iClass = 0; iClass < m_nSavedClassCount; iClass++)
     158             :         {
     159          10 :             GMLFeatureClass *poItem = m_papoSavedClass[iClass];
     160          10 :             if (EQUAL(poItem->GetName(), pItem->GetName()))
     161             :             {
     162           4 :                 poClass = poItem;
     163           4 :                 break;
     164             :             }
     165             :         }
     166           6 :         if (poClass != nullptr)
     167             :         {
     168           4 :             if (poClass->GetFeatureCount() > 0)
     169           4 :                 AddClass(poClass);
     170             :         }
     171           6 :         pItem = pItem->GetNext();
     172             :     }
     173           2 :     SetClassListLocked(true);
     174             : 
     175             :     // Destroying the saved List and any unused FeatureClass.
     176           6 :     for (int iClass = 0; iClass < m_nSavedClassCount; iClass++)
     177             :     {
     178           4 :         bool bUnused = true;
     179           4 :         GMLFeatureClass *poClass = m_papoSavedClass[iClass];
     180           6 :         for (int iClass2 = 0; iClass2 < m_nClassCount; iClass2++)
     181             :         {
     182           6 :             if (m_papoClass[iClass2] == poClass)
     183             :             {
     184           4 :                 bUnused = false;
     185           4 :                 break;
     186             :             }
     187             :         }
     188           4 :         if (bUnused)
     189           0 :             delete poClass;
     190             :     }
     191           2 :     CPLFree(m_papoSavedClass);
     192           2 :     return true;
     193             : }
     194             : 
     195             : /***************************************************/
     196             : /*       GMLReader::PrescanForTemplate()           */
     197             : /***************************************************/
     198             : 
     199           2 : bool GMLReader::PrescanForTemplate()
     200             : {
     201             :     // Below logic is not ready for FeatureProperty/FeaturePropertyList
     202           2 :     if (ShouldLookForClassAtAnyLevel())
     203           2 :         return true;
     204             : 
     205           0 :     GMLFeature *poFeature = nullptr;
     206           0 :     GFSTemplateList *pCC = new GFSTemplateList();
     207             : 
     208             :     // Processing GML features.
     209           0 :     while ((poFeature = NextFeature()) != nullptr)
     210             :     {
     211           0 :         GMLFeatureClass *poClass = poFeature->GetClass();
     212           0 :         const CPLXMLNode *const *papsGeomList = poFeature->GetGeometryList();
     213           0 :         bool b_has_geom = false;
     214             : 
     215           0 :         if (papsGeomList != nullptr)
     216             :         {
     217           0 :             int i = 0;
     218           0 :             const CPLXMLNode *psNode = papsGeomList[i];
     219           0 :             while (psNode != nullptr)
     220             :             {
     221           0 :                 b_has_geom = true;
     222           0 :                 i++;
     223           0 :                 psNode = papsGeomList[i];
     224             :             }
     225             :         }
     226           0 :         pCC->Update(poClass->GetElementName(), b_has_geom);
     227             : 
     228           0 :         delete poFeature;
     229             :     }
     230             : 
     231           0 :     gmlUpdateFeatureClasses(pCC, this, &m_nHasSequentialLayers);
     232           0 :     if (m_nHasSequentialLayers == TRUE)
     233           0 :         ReArrangeTemplateClasses(pCC);
     234           0 :     const int iCount = pCC->GetClassCount();
     235           0 :     delete pCC;
     236           0 :     CleanupParser();
     237           0 :     return iCount > 0;
     238             : }
     239             : 
     240             : /***************************************************/
     241             : /*                 GFSTemplateList()               */
     242             : /***************************************************/
     243             : 
     244           2 : GFSTemplateList::GFSTemplateList()
     245           2 :     : m_bSequentialLayers(true), pFirst(nullptr), pLast(nullptr)
     246             : {
     247           2 : }
     248             : 
     249             : /***************************************************/
     250             : /*                 GFSTemplateList()               */
     251             : /***************************************************/
     252             : 
     253           4 : GFSTemplateList::~GFSTemplateList()
     254             : {
     255           2 :     GFSTemplateItem *pItem = pFirst;
     256           8 :     while (pItem != nullptr)
     257             :     {
     258           6 :         GFSTemplateItem *pNext = pItem->GetNext();
     259           6 :         delete pItem;
     260           6 :         pItem = pNext;
     261             :     }
     262           2 : }
     263             : 
     264             : /***************************************************/
     265             : /*             GFSTemplateList::Insert()           */
     266             : /***************************************************/
     267             : 
     268           6 : GFSTemplateItem *GFSTemplateList::Insert(const char *pszName)
     269             : {
     270           6 :     GFSTemplateItem *pItem = new GFSTemplateItem(pszName);
     271             : 
     272             :     // Inserting into the linked list.
     273           6 :     if (pFirst == nullptr)
     274           2 :         pFirst = pItem;
     275           6 :     if (pLast != nullptr)
     276           4 :         pLast->SetNext(pItem);
     277           6 :     pLast = pItem;
     278           6 :     return pItem;
     279             : }
     280             : 
     281             : /***************************************************/
     282             : /*             GFSTemplateList::Update()           */
     283             : /***************************************************/
     284             : 
     285         138 : void GFSTemplateList::Update(const char *pszName, int bHasGeom)
     286             : {
     287         138 :     GFSTemplateItem *pItem = nullptr;
     288             : 
     289         138 :     if (pFirst == nullptr)
     290             :     {
     291             :         // Empty List: first item.
     292           2 :         pItem = Insert(pszName);
     293           2 :         pItem->Update(bHasGeom);
     294           2 :         return;
     295             :     }
     296         136 :     if (EQUAL(pszName, pLast->GetName()))
     297             :     {
     298             :         // Continuing with the current Class Item.
     299         132 :         pLast->Update(bHasGeom);
     300         132 :         return;
     301             :     }
     302             : 
     303           4 :     pItem = pFirst;
     304          10 :     while (pItem != nullptr)
     305             :     {
     306           6 :         if (EQUAL(pszName, pItem->GetName()))
     307             :         {
     308             :             // Class Item previously declared: NOT SEQUENTIAL.
     309           0 :             m_bSequentialLayers = false;
     310           0 :             pItem->Update(bHasGeom);
     311           0 :             return;
     312             :         }
     313           6 :         pItem = pItem->GetNext();
     314             :     }
     315             : 
     316             :     // Inserting a new Class Item.
     317           4 :     pItem = Insert(pszName);
     318           4 :     pItem->Update(bHasGeom);
     319             : }
     320             : 
     321             : /***************************************************/
     322             : /*          GFSTemplateList::GetClassCount()       */
     323             : /***************************************************/
     324             : 
     325           0 : int GFSTemplateList::GetClassCount()
     326             : {
     327           0 :     int iCount = 0;
     328           0 :     GFSTemplateItem *pItem = pFirst;
     329           0 :     while (pItem != nullptr)
     330             :     {
     331           0 :         iCount++;
     332           0 :         pItem = pItem->GetNext();
     333             :     }
     334             : 
     335           0 :     return iCount;
     336             : }
     337             : 
     338             : /***************************************************/
     339             : /*                 GFSTemplateItem()               */
     340             : /***************************************************/
     341             : 
     342           6 : GFSTemplateItem::GFSTemplateItem(const char *pszName)
     343           6 :     : m_pszName(CPLStrdup(pszName)), n_nItemCount(0), n_nGeomCount(0),
     344           6 :       pNext(nullptr)
     345             : {
     346           6 : }
     347             : 
     348             : /***************************************************/
     349             : /*                ~GFSTemplateItem()               */
     350             : /***************************************************/
     351             : 
     352          12 : GFSTemplateItem::~GFSTemplateItem()
     353             : {
     354           6 :     CPLFree(m_pszName);
     355           6 : }
     356             : 
     357             : /***************************************************/
     358             : /*             GFSTemplateItem::Update()           */
     359             : /***************************************************/
     360             : 
     361         138 : void GFSTemplateItem::Update(int bHasGeom)
     362             : {
     363         138 :     n_nItemCount++;
     364         138 :     if (bHasGeom == TRUE)
     365         138 :         n_nGeomCount++;
     366         138 : }

Generated by: LCOV version 1.14