LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/lvbag - ogrlvbagdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 65 73 89.0 %
Date: 2024-11-21 22:18:42 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  LV BAG Translator
       4             :  * Purpose:  Implements OGRLVBAGDriver.
       5             :  * Author:   Laixer B.V., info at laixer dot com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2020, Laixer B.V. <info at laixer dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_lvbag.h"
      14             : #include "ogrsf_frmts.h"
      15             : 
      16             : /************************************************************************/
      17             : /*                             Identify()                               */
      18             : /************************************************************************/
      19             : 
      20       50012 : static int OGRLVBAGDriverIdentify(GDALOpenInfo *poOpenInfo)
      21             : {
      22       50012 :     if (!poOpenInfo->bStatOK)
      23       43112 :         return FALSE;
      24        6900 :     if (poOpenInfo->bIsDirectory)
      25        1325 :         return -1;  // Check later
      26        5575 :     if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes == 0)
      27         150 :         return FALSE;
      28             : 
      29        5425 :     auto pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      30        5425 :     if (pszPtr[0] != '<')
      31        4274 :         return FALSE;
      32             : 
      33        1151 :     if (poOpenInfo->IsSingleAllowedDriver("LVBAG"))
      34           2 :         return TRUE;
      35             : 
      36             :     // Can't handle mutations just yet
      37        1149 :     if (strstr(pszPtr,
      38             :                "http://www.kadaster.nl/schemas/mutatielevering-generiek/1.0") !=
      39             :         nullptr)
      40           0 :         return FALSE;
      41             : 
      42        1149 :     if (strstr(pszPtr,
      43             :                "http://www.kadaster.nl/schemas/standlevering-generiek/1.0") ==
      44             :         nullptr)
      45        1097 :         return FALSE;
      46             : 
      47             :     // Pin the driver to XSD version 'v20200601'
      48          52 :     if (strstr(pszPtr, "http://www.kadaster.nl/schemas/lvbag/"
      49             :                        "extract-deelbestand-lvc/v20200601") == nullptr)
      50           1 :         return FALSE;
      51             : 
      52          51 :     return TRUE;
      53             : }
      54             : 
      55             : /************************************************************************/
      56             : /*                                Open()                                */
      57             : /************************************************************************/
      58             : 
      59         680 : GDALDataset *OGRLVBAGDriverOpen(GDALOpenInfo *poOpenInfo)
      60             : {
      61         680 :     if (!OGRLVBAGDriverIdentify(poOpenInfo) || poOpenInfo->eAccess == GA_Update)
      62          89 :         return nullptr;
      63             : 
      64         591 :     const char *pszFilename = poOpenInfo->pszFilename;
      65        1182 :     auto poDS = std::unique_ptr<OGRLVBAGDataSource>{new OGRLVBAGDataSource{}};
      66         591 :     poDS->SetDescription(pszFilename);
      67             : 
      68         591 :     if (!poOpenInfo->bIsDirectory && poOpenInfo->fpL != nullptr)
      69             :     {
      70          24 :         if (!poDS->Open(pszFilename, poOpenInfo->papszOpenOptions))
      71           0 :             poDS.reset();
      72             :     }
      73         567 :     else if (poOpenInfo->bIsDirectory && poOpenInfo->fpL == nullptr)
      74             :     {
      75         567 :         int nProbedFileCount = 0;
      76         567 :         bool bFound = false;
      77         567 :         char **papszNames = VSIReadDir(pszFilename);
      78       25352 :         for (int i = 0; papszNames != nullptr && papszNames[i] != nullptr; ++i)
      79             :         {
      80       24785 :             if (!EQUAL(CPLGetExtension(papszNames[i]), "xml"))
      81       24780 :                 continue;
      82             : 
      83             :             const CPLString oSubFilename =
      84          17 :                 CPLFormFilename(pszFilename, papszNames[i], nullptr);
      85             : 
      86          17 :             if (EQUAL(papszNames[i], ".") || EQUAL(papszNames[i], ".."))
      87           0 :                 continue;
      88             : 
      89             :             // Give up on /vsi filesystems if after 10 files we haven't found
      90             :             // a single BAG file
      91          17 :             if (nProbedFileCount == 10 && !bFound &&
      92           1 :                 STARTS_WITH(pszFilename, "/vsi"))
      93             :             {
      94           0 :                 const bool bCheckAllFiles = CPLTestBool(
      95             :                     CPLGetConfigOption("OGR_LVBAG_CHECK_ALL_FILES", "NO"));
      96           0 :                 if (!bCheckAllFiles)
      97           0 :                     break;
      98             :             }
      99             : 
     100          17 :             nProbedFileCount++;
     101          17 :             GDALOpenInfo oOpenInfo{oSubFilename, GA_ReadOnly};
     102          17 :             if (OGRLVBAGDriverIdentify(&oOpenInfo) != TRUE)
     103          12 :                 continue;
     104             : 
     105           5 :             if (poDS->Open(oSubFilename, poOpenInfo->papszOpenOptions))
     106             :             {
     107           5 :                 bFound = true;
     108             :             }
     109             :         }
     110             : 
     111         567 :         CSLDestroy(papszNames);
     112         567 :         if (!poDS->GetLayerCount())
     113             :         {
     114         565 :             poDS.reset();
     115         565 :             return nullptr;
     116           2 :         }
     117             :     }
     118             :     else
     119             :     {
     120           0 :         poDS.reset();
     121           0 :         return nullptr;
     122             :     }
     123             : 
     124          26 :     return poDS.release();
     125             : }
     126             : 
     127             : /************************************************************************/
     128             : /*                         RegisterOGRLVBAG()                           */
     129             : /************************************************************************/
     130             : 
     131        1595 : void RegisterOGRLVBAG()
     132             : {
     133        1595 :     if (GDALGetDriverByName("LVBAG") != nullptr)
     134         302 :         return;
     135             : 
     136        2586 :     auto poDriver = std::make_unique<GDALDriver>();
     137             : 
     138        1293 :     poDriver->SetDescription("LVBAG");
     139        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     140        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Kadaster LV BAG Extract 2.0");
     141        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
     142        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/lvbag.html");
     143        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     144        1293 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     145             : 
     146        1293 :     poDriver->SetMetadataItem(
     147             :         GDAL_DMD_OPENOPTIONLIST,
     148             :         "<OpenOptionList>"
     149             :         "  <Option name='AUTOCORRECT_INVALID_DATA' type='boolean' "
     150             :         "description='whether driver should try to fix invalid data' "
     151             :         "default='NO'/>"
     152             :         "  <Option name='LEGACY_ID' type='boolean' description='whether driver "
     153             :         "should use the BAG 1.0 identifiers' default='NO'/>"
     154        1293 :         "</OpenOptionList>");
     155             : 
     156        1293 :     poDriver->pfnOpen = OGRLVBAGDriverOpen;
     157        1293 :     poDriver->pfnIdentify = OGRLVBAGDriverIdentify;
     158             : 
     159        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver.release());
     160             : }

Generated by: LCOV version 1.14