LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/lvbag - ogrlvbagdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 63 71 88.7 %
Date: 2024-05-14 13:00:50 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             :  * 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
      21             :  * OR 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             : #include "ogr_lvbag.h"
      30             : #include "ogrsf_frmts.h"
      31             : 
      32             : /************************************************************************/
      33             : /*                             Identify()                               */
      34             : /************************************************************************/
      35             : 
      36       46930 : static int OGRLVBAGDriverIdentify(GDALOpenInfo *poOpenInfo)
      37             : {
      38       46930 :     if (!poOpenInfo->bStatOK)
      39       40527 :         return FALSE;
      40        6403 :     if (poOpenInfo->bIsDirectory)
      41        1232 :         return -1;  // Check later
      42        5171 :     if (poOpenInfo->fpL == nullptr)
      43          82 :         return FALSE;
      44             : 
      45        5089 :     auto pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      46        5089 :     if (poOpenInfo->nHeaderBytes == 0 || pszPtr[0] != '<')
      47        4033 :         return FALSE;
      48             : 
      49             :     // Can't handle mutations just yet
      50        1056 :     if (strstr(pszPtr,
      51             :                "http://www.kadaster.nl/schemas/mutatielevering-generiek/1.0") !=
      52             :         nullptr)
      53           0 :         return FALSE;
      54             : 
      55        1056 :     if (strstr(pszPtr,
      56             :                "http://www.kadaster.nl/schemas/standlevering-generiek/1.0") ==
      57             :         nullptr)
      58        1004 :         return FALSE;
      59             : 
      60             :     // Pin the driver to XSD version 'v20200601'
      61          52 :     if (strstr(pszPtr, "http://www.kadaster.nl/schemas/lvbag/"
      62             :                        "extract-deelbestand-lvc/v20200601") == nullptr)
      63           1 :         return FALSE;
      64             : 
      65          51 :     return TRUE;
      66             : }
      67             : 
      68             : /************************************************************************/
      69             : /*                                Open()                                */
      70             : /************************************************************************/
      71             : 
      72         635 : GDALDataset *OGRLVBAGDriverOpen(GDALOpenInfo *poOpenInfo)
      73             : {
      74         635 :     if (!OGRLVBAGDriverIdentify(poOpenInfo) || poOpenInfo->eAccess == GA_Update)
      75          87 :         return nullptr;
      76             : 
      77         548 :     const char *pszFilename = poOpenInfo->pszFilename;
      78        1096 :     auto poDS = std::unique_ptr<OGRLVBAGDataSource>{new OGRLVBAGDataSource{}};
      79         548 :     poDS->SetDescription(pszFilename);
      80             : 
      81         548 :     if (!poOpenInfo->bIsDirectory && poOpenInfo->fpL != nullptr)
      82             :     {
      83          23 :         if (!poDS->Open(pszFilename, poOpenInfo->papszOpenOptions))
      84           0 :             poDS.reset();
      85             :     }
      86         525 :     else if (poOpenInfo->bIsDirectory && poOpenInfo->fpL == nullptr)
      87             :     {
      88         525 :         int nProbedFileCount = 0;
      89         525 :         bool bFound = false;
      90         525 :         char **papszNames = VSIReadDir(pszFilename);
      91       24146 :         for (int i = 0; papszNames != nullptr && papszNames[i] != nullptr; ++i)
      92             :         {
      93       23621 :             if (!EQUAL(CPLGetExtension(papszNames[i]), "xml"))
      94       23616 :                 continue;
      95             : 
      96             :             const CPLString oSubFilename =
      97          17 :                 CPLFormFilename(pszFilename, papszNames[i], nullptr);
      98             : 
      99          17 :             if (EQUAL(papszNames[i], ".") || EQUAL(papszNames[i], ".."))
     100           0 :                 continue;
     101             : 
     102             :             // Give up on /vsi filesystems if after 10 files we haven't found
     103             :             // a single BAG file
     104          17 :             if (nProbedFileCount == 10 && !bFound &&
     105           1 :                 STARTS_WITH(pszFilename, "/vsi"))
     106             :             {
     107           0 :                 const bool bCheckAllFiles = CPLTestBool(
     108             :                     CPLGetConfigOption("OGR_LVBAG_CHECK_ALL_FILES", "NO"));
     109           0 :                 if (!bCheckAllFiles)
     110           0 :                     break;
     111             :             }
     112             : 
     113          17 :             nProbedFileCount++;
     114          17 :             GDALOpenInfo oOpenInfo{oSubFilename, GA_ReadOnly};
     115          17 :             if (OGRLVBAGDriverIdentify(&oOpenInfo) != TRUE)
     116          12 :                 continue;
     117             : 
     118           5 :             if (poDS->Open(oSubFilename, poOpenInfo->papszOpenOptions))
     119             :             {
     120           5 :                 bFound = true;
     121             :             }
     122             :         }
     123             : 
     124         525 :         CSLDestroy(papszNames);
     125         525 :         if (!poDS->GetLayerCount())
     126             :         {
     127         523 :             poDS.reset();
     128         523 :             return nullptr;
     129           2 :         }
     130             :     }
     131             :     else
     132             :     {
     133           0 :         poDS.reset();
     134           0 :         return nullptr;
     135             :     }
     136             : 
     137          25 :     return poDS.release();
     138             : }
     139             : 
     140             : /************************************************************************/
     141             : /*                         RegisterOGRLVBAG()                           */
     142             : /************************************************************************/
     143             : 
     144        1522 : void RegisterOGRLVBAG()
     145             : {
     146        1522 :     if (GDALGetDriverByName("LVBAG") != nullptr)
     147         301 :         return;
     148             : 
     149        2442 :     auto poDriver = std::make_unique<GDALDriver>();
     150             : 
     151        1221 :     poDriver->SetDescription("LVBAG");
     152        1221 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     153        1221 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Kadaster LV BAG Extract 2.0");
     154        1221 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
     155        1221 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/lvbag.html");
     156        1221 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     157        1221 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     158             : 
     159        1221 :     poDriver->SetMetadataItem(
     160             :         GDAL_DMD_OPENOPTIONLIST,
     161             :         "<OpenOptionList>"
     162             :         "  <Option name='AUTOCORRECT_INVALID_DATA' type='boolean' "
     163             :         "description='whether driver should try to fix invalid data' "
     164             :         "default='NO'/>"
     165             :         "  <Option name='LEGACY_ID' type='boolean' description='whether driver "
     166             :         "should use the BAG 1.0 identifiers' default='NO'/>"
     167        1221 :         "</OpenOptionList>");
     168             : 
     169        1221 :     poDriver->pfnOpen = OGRLVBAGDriverOpen;
     170        1221 :     poDriver->pfnIdentify = OGRLVBAGDriverIdentify;
     171             : 
     172        1221 :     GetGDALDriverManager()->RegisterDriver(poDriver.release());
     173             : }

Generated by: LCOV version 1.14