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-04-29 17:29:47 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_conv.h"
      31             : #include "cpl_string.h"
      32             : 
      33             : #include "ili2reader.h"
      34             : 
      35             : #include "ogr_ili2.h"
      36             : 
      37             : using namespace std;
      38             : 
      39             : /************************************************************************/
      40             : /*                         OGRILI2DataSource()                         */
      41             : /************************************************************************/
      42             : 
      43          81 : OGRILI2DataSource::OGRILI2DataSource()
      44          81 :     : pszName(nullptr), poImdReader(new ImdReader(2)), poReader(nullptr),
      45          81 :       fpOutput(nullptr), nLayers(0), papoLayers(nullptr)
      46             : {
      47          81 : }
      48             : 
      49             : /************************************************************************/
      50             : /*                        ~OGRILI2DataSource()                         */
      51             : /************************************************************************/
      52             : 
      53         162 : OGRILI2DataSource::~OGRILI2DataSource()
      54             : 
      55             : {
      56          83 :     for (int i = 0; i < nLayers; i++)
      57             :     {
      58           2 :         delete papoLayers[i];
      59             :     }
      60          81 :     CPLFree(papoLayers);
      61             : 
      62          81 :     if (fpOutput != nullptr)
      63             :     {
      64           1 :         VSIFPrintfL(fpOutput, "</%s>\n", poImdReader->mainBasketName.c_str());
      65           1 :         VSIFPrintfL(fpOutput, "</DATASECTION>\n");
      66           1 :         VSIFPrintfL(fpOutput, "</TRANSFER>\n");
      67           1 :         VSIFCloseL(fpOutput);
      68             :     }
      69             : 
      70          81 :     DestroyILI2Reader(poReader);
      71          81 :     delete poImdReader;
      72          81 :     CPLFree(pszName);
      73         162 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                                Open()                                */
      77             : /************************************************************************/
      78             : 
      79          61 : int OGRILI2DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
      80             :                             int bTestOpen)
      81             : 
      82             : {
      83         122 :     CPLString osBasename;
      84         122 :     CPLString osModelFilename;
      85             : 
      86          61 :     if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr)
      87             :     {
      88           0 :         osBasename = pszNewName;
      89           0 :         osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
      90             :     }
      91             :     else
      92             :     {
      93          61 :         char **filenames = CSLTokenizeString2(pszNewName, ",", 0);
      94          61 :         int nCount = CSLCount(filenames);
      95          61 :         if (nCount == 0)
      96             :         {
      97           0 :             CSLDestroy(filenames);
      98           0 :             return FALSE;
      99             :         }
     100          61 :         osBasename = filenames[0];
     101             : 
     102          61 :         if (nCount > 1)
     103          57 :             osModelFilename = filenames[1];
     104             : 
     105          61 :         CSLDestroy(filenames);
     106             :     }
     107             : 
     108          61 :     pszName = CPLStrdup(osBasename);
     109             : 
     110             :     /* -------------------------------------------------------------------- */
     111             :     /*      Open the source file.                                           */
     112             :     /* -------------------------------------------------------------------- */
     113          61 :     VSILFILE *fp = VSIFOpenL(pszName, "r");
     114          61 :     if (fp == nullptr)
     115             :     {
     116          57 :         if (!bTestOpen)
     117           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
     118             :                      "Failed to open ILI2 file `%s'.", pszNewName);
     119             : 
     120          57 :         return FALSE;
     121             :     }
     122             : 
     123             :     /* -------------------------------------------------------------------- */
     124             :     /*      If we aren't sure it is ILI2, load a header chunk and check     */
     125             :     /*      for signs it is ILI2                                            */
     126             :     /* -------------------------------------------------------------------- */
     127             :     char szHeader[1000];
     128           4 :     if (bTestOpen)
     129             :     {
     130             :         int nLen =
     131           4 :             static_cast<int>(VSIFReadL(szHeader, 1, sizeof(szHeader), fp));
     132           4 :         if (nLen == sizeof(szHeader))
     133           4 :             szHeader[sizeof(szHeader) - 1] = '\0';
     134             :         else
     135           0 :             szHeader[nLen] = '\0';
     136             : 
     137           4 :         if (szHeader[0] != '<' ||
     138           4 :             strstr(szHeader, "interlis.ch/INTERLIS2") == nullptr)
     139             :         {
     140             :             // "www.interlis.ch/INTERLIS2.3"
     141           0 :             VSIFCloseL(fp);
     142           0 :             return FALSE;
     143             :         }
     144             :     }
     145             : 
     146             :     /* -------------------------------------------------------------------- */
     147             :     /*      We assume now that it is ILI2.  Close and instantiate a         */
     148             :     /*      ILI2Reader on it.                                               */
     149             :     /* -------------------------------------------------------------------- */
     150           4 :     VSIFCloseL(fp);
     151             : 
     152           4 :     poReader = CreateILI2Reader();
     153           4 :     if (poReader == nullptr)
     154             :     {
     155           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     156             :                  "File %s appears to be ILI2 but the ILI2 reader cannot\n"
     157             :                  "be instantiated, likely because Xerces support was not\n"
     158             :                  "configured in.",
     159             :                  pszNewName);
     160           0 :         return FALSE;
     161             :     }
     162             : 
     163           4 :     if (!osModelFilename.empty())
     164           3 :         poReader->ReadModel(this, poImdReader, osModelFilename);
     165             : 
     166           4 :     poReader->SetSourceFile(pszName);
     167             : 
     168           4 :     poReader->SaveClasses(pszName);
     169             : 
     170           4 :     listLayer = poReader->GetLayers();
     171           4 :     list<OGRLayer *>::const_iterator layerIt;
     172          48 :     for (layerIt = listLayer.begin(); layerIt != listLayer.end(); ++layerIt)
     173             :     {
     174          44 :         (*layerIt)->ResetReading();
     175             :     }
     176             : 
     177           4 :     return TRUE;
     178             : }
     179             : 
     180             : /************************************************************************/
     181             : /*                               Create()                               */
     182             : /************************************************************************/
     183             : 
     184          20 : int OGRILI2DataSource::Create(const char *pszFilename,
     185             :                               CPL_UNUSED char **papszOptions)
     186             : 
     187             : {
     188          20 :     char **filenames = CSLTokenizeString2(pszFilename, ",", 0);
     189          20 :     pszName = CPLStrdup(filenames[0]);
     190             :     const char *pszModelFilename =
     191          20 :         (CSLCount(filenames) > 1) ? filenames[1] : nullptr;
     192             : 
     193          20 :     if (pszModelFilename == nullptr)
     194             :     {
     195          18 :         CPLError(
     196             :             CE_Failure, CPLE_AppDefined,
     197             :             "ILI2 Create(): model file not specified in destination filename.");
     198          18 :         CSLDestroy(filenames);
     199          18 :         return FALSE;
     200             :     }
     201             : 
     202             :     /* -------------------------------------------------------------------- */
     203             :     /*      Create the output file.                                         */
     204             :     /* -------------------------------------------------------------------- */
     205             : 
     206           2 :     if (strcmp(pszName, "/vsistdout/") == 0 ||
     207           2 :         STARTS_WITH(pszName, "/vsigzip/"))
     208             :     {
     209           0 :         fpOutput = VSIFOpenL(pszName, "wb");
     210             :     }
     211           2 :     else if (STARTS_WITH(pszName, "/vsizip/"))
     212             :     {
     213           0 :         if (EQUAL(CPLGetExtension(pszName), "zip"))
     214             :         {
     215             :             char *pszNewName =
     216           0 :                 CPLStrdup(CPLFormFilename(pszName, "out.xtf", nullptr));
     217           0 :             CPLFree(pszName);
     218           0 :             pszName = pszNewName;
     219             :         }
     220             : 
     221           0 :         fpOutput = VSIFOpenL(pszName, "wb");
     222             :     }
     223             :     else
     224           2 :         fpOutput = VSIFOpenL(pszName, "wb+");
     225           2 :     if (fpOutput == nullptr)
     226             :     {
     227           1 :         CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create XTF file %s.",
     228             :                  pszName);
     229           1 :         CSLDestroy(filenames);
     230           1 :         return FALSE;
     231             :     }
     232             : 
     233             :     /* -------------------------------------------------------------------- */
     234             :     /*      Parse model                                                     */
     235             :     /* -------------------------------------------------------------------- */
     236           1 :     poImdReader->ReadModel(pszModelFilename);
     237             : 
     238             :     /* -------------------------------------------------------------------- */
     239             :     /*      Write headers                                                   */
     240             :     /* -------------------------------------------------------------------- */
     241           1 :     VSIFPrintfL(fpOutput, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
     242           1 :     VSIFPrintfL(fpOutput,
     243             :                 "<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
     244           1 :     VSIFPrintfL(fpOutput,
     245             :                 "<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n",
     246             :                 GDALVersionInfo("RELEASE_NAME"));
     247           1 :     VSIFPrintfL(fpOutput, "<MODELS>\n");
     248           3 :     for (IliModelInfos::const_iterator it = poImdReader->modelInfos.begin();
     249           5 :          it != poImdReader->modelInfos.end(); ++it)
     250             :     {
     251           6 :         VSIFPrintfL(fpOutput,
     252             :                     "<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
     253           6 :                     it->name.c_str(), it->uri.c_str(), it->version.c_str());
     254             :     }
     255           1 :     VSIFPrintfL(fpOutput, "</MODELS>\n");
     256           1 :     VSIFPrintfL(fpOutput, "</HEADERSECTION>\n");
     257           1 :     VSIFPrintfL(fpOutput, "<DATASECTION>\n");
     258           1 :     const char *basketName = poImdReader->mainBasketName.c_str();
     259           1 :     VSIFPrintfL(fpOutput, "<%s BID=\"%s\">\n", basketName, basketName);
     260             : 
     261           1 :     CSLDestroy(filenames);
     262           1 :     return TRUE;
     263             : }
     264             : 
     265             : /************************************************************************/
     266             : /*                           ICreateLayer()                             */
     267             : /************************************************************************/
     268             : 
     269             : OGRLayer *
     270           2 : OGRILI2DataSource::ICreateLayer(const char *pszLayerName,
     271             :                                 const OGRGeomFieldDefn *poGeomFieldDefn,
     272             :                                 CSLConstList /*papszOptions*/)
     273             : {
     274           2 :     if (fpOutput == nullptr)
     275           0 :         return nullptr;
     276             : 
     277           2 :     const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     278             : 
     279             :     FeatureDefnInfo featureDefnInfo =
     280           2 :         poImdReader->GetFeatureDefnInfo(pszLayerName);
     281           2 :     OGRFeatureDefn *poFeatureDefn = featureDefnInfo.GetTableDefnRef();
     282           2 :     if (poFeatureDefn == nullptr)
     283             :     {
     284           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     285             :                  "Layer '%s' not found in model definition. "
     286             :                  "Creating adhoc layer",
     287             :                  pszLayerName);
     288           0 :         poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     289           0 :         poFeatureDefn->SetGeomType(eType);
     290             :     }
     291             :     OGRILI2Layer *poLayer =
     292           2 :         new OGRILI2Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
     293             : 
     294           2 :     nLayers++;
     295           2 :     papoLayers = static_cast<OGRILI2Layer **>(
     296           2 :         CPLRealloc(papoLayers, sizeof(OGRILI2Layer *) * nLayers));
     297           2 :     papoLayers[nLayers - 1] = poLayer;
     298             : 
     299           2 :     return poLayer;
     300             : }
     301             : 
     302             : /************************************************************************/
     303             : /*                           TestCapability()                           */
     304             : /************************************************************************/
     305             : 
     306           0 : int OGRILI2DataSource::TestCapability(const char *pszCap)
     307             : 
     308             : {
     309           0 :     if (EQUAL(pszCap, ODsCCreateLayer))
     310           0 :         return TRUE;
     311           0 :     else if (EQUAL(pszCap, ODsCCurveGeometries))
     312           0 :         return TRUE;
     313           0 :     else if (EQUAL(pszCap, ODsCZGeometries))
     314           0 :         return TRUE;
     315             : 
     316           0 :     return FALSE;
     317             : }
     318             : 
     319             : /************************************************************************/
     320             : /*                              GetLayer()                              */
     321             : /************************************************************************/
     322             : 
     323          81 : OGRLayer *OGRILI2DataSource::GetLayer(int iLayer)
     324             : 
     325             : {
     326          81 :     list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
     327          81 :     int i = 0;
     328         730 :     while (i < iLayer && layerIt != listLayer.end())
     329             :     {
     330         649 :         ++i;
     331         649 :         ++layerIt;
     332             :     }
     333             : 
     334          81 :     if (i == iLayer && layerIt != listLayer.end())
     335             :     {
     336          81 :         OGRILI2Layer *tmpLayer = reinterpret_cast<OGRILI2Layer *>(*layerIt);
     337          81 :         return tmpLayer;
     338             :     }
     339             : 
     340           0 :     return nullptr;
     341             : }

Generated by: LCOV version 1.14