LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ili - ogrili2datasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 104 133 78.2 %
Date: 2024-11-25 23:50:41 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Interlis 2 Translator
       4             :  * Purpose:  Implements OGRILI2DataSource class.
       5             :  * Author:   Markus Schnider, Sourcepole AG
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
       9             :  * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : 
      17             : #include "ili2reader.h"
      18             : 
      19             : #include "ogr_ili2.h"
      20             : 
      21             : using namespace std;
      22             : 
      23             : /************************************************************************/
      24             : /*                         OGRILI2DataSource()                         */
      25             : /************************************************************************/
      26             : 
      27          81 : OGRILI2DataSource::OGRILI2DataSource()
      28          81 :     : pszName(nullptr), poImdReader(new ImdReader(2)), poReader(nullptr),
      29          81 :       fpOutput(nullptr), nLayers(0), papoLayers(nullptr)
      30             : {
      31          81 : }
      32             : 
      33             : /************************************************************************/
      34             : /*                        ~OGRILI2DataSource()                         */
      35             : /************************************************************************/
      36             : 
      37         162 : OGRILI2DataSource::~OGRILI2DataSource()
      38             : 
      39             : {
      40          83 :     for (int i = 0; i < nLayers; i++)
      41             :     {
      42           2 :         delete papoLayers[i];
      43             :     }
      44          81 :     CPLFree(papoLayers);
      45             : 
      46          81 :     if (fpOutput != nullptr)
      47             :     {
      48           1 :         VSIFPrintfL(fpOutput, "</%s>\n", poImdReader->mainBasketName.c_str());
      49           1 :         VSIFPrintfL(fpOutput, "</DATASECTION>\n");
      50           1 :         VSIFPrintfL(fpOutput, "</TRANSFER>\n");
      51           1 :         VSIFCloseL(fpOutput);
      52             :     }
      53             : 
      54          81 :     DestroyILI2Reader(poReader);
      55          81 :     delete poImdReader;
      56          81 :     CPLFree(pszName);
      57         162 : }
      58             : 
      59             : /************************************************************************/
      60             : /*                                Open()                                */
      61             : /************************************************************************/
      62             : 
      63          61 : int OGRILI2DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
      64             :                             int bTestOpen)
      65             : 
      66             : {
      67         122 :     CPLString osBasename;
      68         122 :     CPLString osModelFilename;
      69             : 
      70          61 :     if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr)
      71             :     {
      72           0 :         osBasename = pszNewName;
      73           0 :         osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
      74             :     }
      75             :     else
      76             :     {
      77          61 :         char **filenames = CSLTokenizeString2(pszNewName, ",", 0);
      78          61 :         int nCount = CSLCount(filenames);
      79          61 :         if (nCount == 0)
      80             :         {
      81           0 :             CSLDestroy(filenames);
      82           0 :             return FALSE;
      83             :         }
      84          61 :         osBasename = filenames[0];
      85             : 
      86          61 :         if (nCount > 1)
      87          57 :             osModelFilename = filenames[1];
      88             : 
      89          61 :         CSLDestroy(filenames);
      90             :     }
      91             : 
      92          61 :     pszName = CPLStrdup(osBasename);
      93             : 
      94             :     /* -------------------------------------------------------------------- */
      95             :     /*      Open the source file.                                           */
      96             :     /* -------------------------------------------------------------------- */
      97          61 :     VSILFILE *fp = VSIFOpenL(pszName, "r");
      98          61 :     if (fp == nullptr)
      99             :     {
     100          57 :         if (!bTestOpen)
     101           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
     102             :                      "Failed to open ILI2 file `%s'.", pszNewName);
     103             : 
     104          57 :         return FALSE;
     105             :     }
     106             : 
     107             :     /* -------------------------------------------------------------------- */
     108             :     /*      If we aren't sure it is ILI2, load a header chunk and check     */
     109             :     /*      for signs it is ILI2                                            */
     110             :     /* -------------------------------------------------------------------- */
     111             :     char szHeader[1000];
     112           4 :     if (bTestOpen)
     113             :     {
     114             :         int nLen =
     115           4 :             static_cast<int>(VSIFReadL(szHeader, 1, sizeof(szHeader), fp));
     116           4 :         if (nLen == sizeof(szHeader))
     117           4 :             szHeader[sizeof(szHeader) - 1] = '\0';
     118             :         else
     119           0 :             szHeader[nLen] = '\0';
     120             : 
     121           4 :         if (szHeader[0] != '<' ||
     122           4 :             strstr(szHeader, "interlis.ch/INTERLIS2") == nullptr)
     123             :         {
     124             :             // "www.interlis.ch/INTERLIS2.3"
     125           0 :             VSIFCloseL(fp);
     126           0 :             return FALSE;
     127             :         }
     128             :     }
     129             : 
     130             :     /* -------------------------------------------------------------------- */
     131             :     /*      We assume now that it is ILI2.  Close and instantiate a         */
     132             :     /*      ILI2Reader on it.                                               */
     133             :     /* -------------------------------------------------------------------- */
     134           4 :     VSIFCloseL(fp);
     135             : 
     136           4 :     poReader = CreateILI2Reader();
     137           4 :     if (poReader == nullptr)
     138             :     {
     139           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     140             :                  "File %s appears to be ILI2 but the ILI2 reader cannot\n"
     141             :                  "be instantiated, likely because Xerces support was not\n"
     142             :                  "configured in.",
     143             :                  pszNewName);
     144           0 :         return FALSE;
     145             :     }
     146             : 
     147           4 :     if (!osModelFilename.empty())
     148           3 :         poReader->ReadModel(this, poImdReader, osModelFilename);
     149             : 
     150           4 :     poReader->SetSourceFile(pszName);
     151             : 
     152           4 :     poReader->SaveClasses(pszName);
     153             : 
     154           4 :     listLayer = poReader->GetLayers();
     155           4 :     list<OGRLayer *>::const_iterator layerIt;
     156          48 :     for (layerIt = listLayer.begin(); layerIt != listLayer.end(); ++layerIt)
     157             :     {
     158          44 :         (*layerIt)->ResetReading();
     159             :     }
     160             : 
     161           4 :     return TRUE;
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                               Create()                               */
     166             : /************************************************************************/
     167             : 
     168          20 : int OGRILI2DataSource::Create(const char *pszFilename,
     169             :                               CPL_UNUSED char **papszOptions)
     170             : 
     171             : {
     172          20 :     char **filenames = CSLTokenizeString2(pszFilename, ",", 0);
     173          20 :     pszName = CPLStrdup(filenames[0]);
     174             :     const char *pszModelFilename =
     175          20 :         (CSLCount(filenames) > 1) ? filenames[1] : nullptr;
     176             : 
     177          20 :     if (pszModelFilename == nullptr)
     178             :     {
     179          18 :         CPLError(
     180             :             CE_Failure, CPLE_AppDefined,
     181             :             "ILI2 Create(): model file not specified in destination filename.");
     182          18 :         CSLDestroy(filenames);
     183          18 :         return FALSE;
     184             :     }
     185             : 
     186             :     /* -------------------------------------------------------------------- */
     187             :     /*      Create the output file.                                         */
     188             :     /* -------------------------------------------------------------------- */
     189             : 
     190           2 :     if (strcmp(pszName, "/vsistdout/") == 0 ||
     191           2 :         STARTS_WITH(pszName, "/vsigzip/"))
     192             :     {
     193           0 :         fpOutput = VSIFOpenL(pszName, "wb");
     194             :     }
     195           2 :     else if (STARTS_WITH(pszName, "/vsizip/"))
     196             :     {
     197           0 :         if (EQUAL(CPLGetExtension(pszName), "zip"))
     198             :         {
     199             :             char *pszNewName =
     200           0 :                 CPLStrdup(CPLFormFilename(pszName, "out.xtf", nullptr));
     201           0 :             CPLFree(pszName);
     202           0 :             pszName = pszNewName;
     203             :         }
     204             : 
     205           0 :         fpOutput = VSIFOpenL(pszName, "wb");
     206             :     }
     207             :     else
     208           2 :         fpOutput = VSIFOpenL(pszName, "wb+");
     209           2 :     if (fpOutput == nullptr)
     210             :     {
     211           1 :         CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create XTF file %s.",
     212             :                  pszName);
     213           1 :         CSLDestroy(filenames);
     214           1 :         return FALSE;
     215             :     }
     216             : 
     217             :     /* -------------------------------------------------------------------- */
     218             :     /*      Parse model                                                     */
     219             :     /* -------------------------------------------------------------------- */
     220           1 :     poImdReader->ReadModel(pszModelFilename);
     221             : 
     222             :     /* -------------------------------------------------------------------- */
     223             :     /*      Write headers                                                   */
     224             :     /* -------------------------------------------------------------------- */
     225           1 :     VSIFPrintfL(fpOutput, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
     226           1 :     VSIFPrintfL(fpOutput,
     227             :                 "<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
     228           1 :     VSIFPrintfL(fpOutput,
     229             :                 "<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n",
     230             :                 GDALVersionInfo("RELEASE_NAME"));
     231           1 :     VSIFPrintfL(fpOutput, "<MODELS>\n");
     232           3 :     for (IliModelInfos::const_iterator it = poImdReader->modelInfos.begin();
     233           5 :          it != poImdReader->modelInfos.end(); ++it)
     234             :     {
     235           6 :         VSIFPrintfL(fpOutput,
     236             :                     "<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
     237           6 :                     it->name.c_str(), it->uri.c_str(), it->version.c_str());
     238             :     }
     239           1 :     VSIFPrintfL(fpOutput, "</MODELS>\n");
     240           1 :     VSIFPrintfL(fpOutput, "</HEADERSECTION>\n");
     241           1 :     VSIFPrintfL(fpOutput, "<DATASECTION>\n");
     242           1 :     const char *basketName = poImdReader->mainBasketName.c_str();
     243           1 :     VSIFPrintfL(fpOutput, "<%s BID=\"%s\">\n", basketName, basketName);
     244             : 
     245           1 :     CSLDestroy(filenames);
     246           1 :     return TRUE;
     247             : }
     248             : 
     249             : /************************************************************************/
     250             : /*                           ICreateLayer()                             */
     251             : /************************************************************************/
     252             : 
     253             : OGRLayer *
     254           2 : OGRILI2DataSource::ICreateLayer(const char *pszLayerName,
     255             :                                 const OGRGeomFieldDefn *poGeomFieldDefn,
     256             :                                 CSLConstList /*papszOptions*/)
     257             : {
     258           2 :     if (fpOutput == nullptr)
     259           0 :         return nullptr;
     260             : 
     261           2 :     const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     262             : 
     263             :     FeatureDefnInfo featureDefnInfo =
     264           2 :         poImdReader->GetFeatureDefnInfo(pszLayerName);
     265           2 :     OGRFeatureDefn *poFeatureDefn = featureDefnInfo.GetTableDefnRef();
     266           2 :     if (poFeatureDefn == nullptr)
     267             :     {
     268           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     269             :                  "Layer '%s' not found in model definition. "
     270             :                  "Creating adhoc layer",
     271             :                  pszLayerName);
     272           0 :         poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     273           0 :         poFeatureDefn->SetGeomType(eType);
     274             :     }
     275             :     OGRILI2Layer *poLayer =
     276           2 :         new OGRILI2Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
     277             : 
     278           2 :     nLayers++;
     279           2 :     papoLayers = static_cast<OGRILI2Layer **>(
     280           2 :         CPLRealloc(papoLayers, sizeof(OGRILI2Layer *) * nLayers));
     281           2 :     papoLayers[nLayers - 1] = poLayer;
     282             : 
     283           2 :     return poLayer;
     284             : }
     285             : 
     286             : /************************************************************************/
     287             : /*                           TestCapability()                           */
     288             : /************************************************************************/
     289             : 
     290           0 : int OGRILI2DataSource::TestCapability(const char *pszCap)
     291             : 
     292             : {
     293           0 :     if (EQUAL(pszCap, ODsCCreateLayer))
     294           0 :         return TRUE;
     295           0 :     else if (EQUAL(pszCap, ODsCCurveGeometries))
     296           0 :         return TRUE;
     297           0 :     else if (EQUAL(pszCap, ODsCZGeometries))
     298           0 :         return TRUE;
     299             : 
     300           0 :     return FALSE;
     301             : }
     302             : 
     303             : /************************************************************************/
     304             : /*                              GetLayer()                              */
     305             : /************************************************************************/
     306             : 
     307          81 : OGRLayer *OGRILI2DataSource::GetLayer(int iLayer)
     308             : 
     309             : {
     310          81 :     list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
     311          81 :     int i = 0;
     312         730 :     while (i < iLayer && layerIt != listLayer.end())
     313             :     {
     314         649 :         ++i;
     315         649 :         ++layerIt;
     316             :     }
     317             : 
     318          81 :     if (i == iLayer && layerIt != listLayer.end())
     319             :     {
     320          81 :         OGRILI2Layer *tmpLayer = reinterpret_cast<OGRILI2Layer *>(*layerIt);
     321          81 :         return tmpLayer;
     322             :     }
     323             : 
     324           0 :     return nullptr;
     325             : }

Generated by: LCOV version 1.14