LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/nas - ogrnasdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 85 124 68.5 %
Date: 2024-05-03 15:49:35 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGR
       4             :  * Purpose:  Implements OGRNASDataSource class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2010-2013, 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             : #include "ogr_nas.h"
      33             : 
      34             : static const char *const apszURNNames[] = {
      35             :     "DE_DHDN_3GK2_*", "EPSG:31466", "DE_DHDN_3GK3_*", "EPSG:31467",
      36             :     "ETRS89_UTM32",   "EPSG:25832", "ETRS89_UTM33",   "EPSG:25833",
      37             :     nullptr,          nullptr};
      38             : 
      39             : /************************************************************************/
      40             : /*                         OGRNASDataSource()                           */
      41             : /************************************************************************/
      42             : 
      43           3 : OGRNASDataSource::OGRNASDataSource()
      44           3 :     : papoLayers(nullptr), nLayers(0), pszName(nullptr), poReader(nullptr)
      45             : {
      46           3 : }
      47             : 
      48             : /************************************************************************/
      49             : /*                        ~OGRNASDataSource()                         */
      50             : /************************************************************************/
      51             : 
      52           6 : OGRNASDataSource::~OGRNASDataSource()
      53             : 
      54             : {
      55           3 :     CPLFree(pszName);
      56             : 
      57           6 :     for (int i = 0; i < nLayers; i++)
      58           3 :         delete papoLayers[i];
      59             : 
      60           3 :     CPLFree(papoLayers);
      61             : 
      62           3 :     if (poReader)
      63           3 :         delete poReader;
      64           6 : }
      65             : 
      66             : /************************************************************************/
      67             : /*                                Open()                                */
      68             : /************************************************************************/
      69             : 
      70           3 : int OGRNASDataSource::Open(const char *pszNewName)
      71             : 
      72             : {
      73           3 :     poReader = CreateNASReader();
      74           3 :     if (poReader == nullptr)
      75             :     {
      76           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      77             :                  "File %s appears to be NAS but the NAS reader cannot\n"
      78             :                  "be instantiated, likely because Xerces support was not\n"
      79             :                  "configured in.",
      80             :                  pszNewName);
      81           0 :         return FALSE;
      82             :     }
      83             : 
      84           3 :     poReader->SetSourceFile(pszNewName);
      85             : 
      86           3 :     pszName = CPLStrdup(pszNewName);
      87             : 
      88           3 :     bool bHaveSchema = false;
      89           3 :     bool bHaveTemplate = false;
      90             :     const char *pszGFSFilename;
      91             :     VSIStatBufL sGFSStatBuf;
      92             : 
      93             :     // Is some NAS Feature Schema (.gfs) TEMPLATE required?
      94           3 :     const char *pszNASTemplateName = CPLGetConfigOption("NAS_GFS_TEMPLATE", "");
      95           3 :     if (!EQUAL(pszNASTemplateName, ""))
      96             :     {
      97             :         // Load the TEMPLATE.
      98           0 :         if (!poReader->LoadClasses(pszNASTemplateName))
      99             :         {
     100           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     101             :                      "NAS schema %s could not be loaded\n", pszNASTemplateName);
     102           0 :             return FALSE;
     103             :         }
     104             : 
     105           0 :         bHaveTemplate = true;
     106             : 
     107           0 :         CPLDebug("NAS", "Schema loaded.");
     108             :     }
     109             :     else
     110             :     {
     111             :         /* --------------------------------------------------------------------
     112             :          */
     113             :         /*      Can we find a NAS Feature Schema (.gfs) for the input file? */
     114             :         /* --------------------------------------------------------------------
     115             :          */
     116           3 :         pszGFSFilename = CPLResetExtension(pszNewName, "gfs");
     117           3 :         if (VSIStatL(pszGFSFilename, &sGFSStatBuf) == 0)
     118             :         {
     119             :             VSIStatBufL sNASStatBuf;
     120           0 :             if (VSIStatL(pszNewName, &sNASStatBuf) == 0 &&
     121           0 :                 sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime)
     122             :             {
     123           0 :                 CPLDebug("NAS",
     124             :                          "Found %s but ignoring because it appears "
     125             :                          "be older than the associated NAS file.",
     126             :                          pszGFSFilename);
     127             :             }
     128             :             else
     129             :             {
     130           0 :                 bHaveSchema = poReader->LoadClasses(pszGFSFilename);
     131             :             }
     132             :         }
     133             : 
     134           3 :         if (!bHaveSchema)
     135             :         {
     136           3 :             CPLError(CE_Failure, CPLE_AppDefined,
     137             :                      "No schema information loaded");
     138             :         }
     139             :     }
     140             : 
     141             :     /* -------------------------------------------------------------------- */
     142             :     /*      Force a first pass to establish the schema.  The loaded schema  */
     143             :     /*      if any will be cleaned from any unavailable classes.            */
     144             :     /* -------------------------------------------------------------------- */
     145           3 :     CPLErrorReset();
     146           4 :     if (!bHaveSchema && !poReader->PrescanForSchema(TRUE) &&
     147           1 :         CPLGetLastErrorType() == CE_Failure)
     148             :     {
     149             :         // Assume an error has been reported.
     150           0 :         return FALSE;
     151             :     }
     152             : 
     153             :     /* -------------------------------------------------------------------- */
     154             :     /*      Save the schema file if possible.  Do not make a fuss if we     */
     155             :     /*      cannot.  It could be read-only directory or something.          */
     156             :     /* -------------------------------------------------------------------- */
     157           3 :     if (!bHaveTemplate && !bHaveSchema && poReader->GetClassCount() > 0 &&
     158           2 :         !STARTS_WITH_CI(pszNewName, "/vsitar/") &&
     159           2 :         !STARTS_WITH_CI(pszNewName, "/vsizip/") &&
     160           2 :         !STARTS_WITH_CI(pszNewName, "/vsigzip/vsi") &&
     161           2 :         !STARTS_WITH_CI(pszNewName, "/vsigzip//vsi") &&
     162           8 :         !STARTS_WITH_CI(pszNewName, "/vsicurl/") &&
     163           2 :         !STARTS_WITH_CI(pszNewName, "/vsicurl_streaming/"))
     164             :     {
     165           2 :         VSILFILE *fp = nullptr;
     166             : 
     167           2 :         pszGFSFilename = CPLResetExtension(pszNewName, "gfs");
     168           4 :         if (VSIStatL(pszGFSFilename, &sGFSStatBuf) != 0 &&
     169           2 :             (fp = VSIFOpenL(pszGFSFilename, "wt")) != nullptr)
     170             :         {
     171           2 :             VSIFCloseL(fp);
     172           2 :             poReader->SaveClasses(pszGFSFilename);
     173             :         }
     174             :         else
     175             :         {
     176           0 :             CPLDebug("NAS",
     177             :                      "Not saving %s. File already exists or can't be created.",
     178             :                      pszGFSFilename);
     179             :         }
     180             :     }
     181             : 
     182             :     /* -------------------------------------------------------------------- */
     183             :     /*      Translate the GMLFeatureClasses into layers.                    */
     184             :     /* -------------------------------------------------------------------- */
     185           6 :     papoLayers = (OGRLayer **)CPLCalloc(sizeof(OGRNASLayer *),
     186           3 :                                         poReader->GetClassCount() + 1);
     187           3 :     nLayers = 0;
     188             : 
     189           6 :     while (nLayers < poReader->GetClassCount())
     190             :     {
     191           3 :         papoLayers[nLayers] = TranslateNASSchema(poReader->GetClass(nLayers));
     192           3 :         nLayers++;
     193             :     }
     194             : 
     195           3 :     return TRUE;
     196             : }
     197             : 
     198             : /************************************************************************/
     199             : /*                         TranslateNASSchema()                         */
     200             : /************************************************************************/
     201             : 
     202           3 : OGRNASLayer *OGRNASDataSource::TranslateNASSchema(GMLFeatureClass *poClass)
     203             : 
     204             : {
     205             :     /* -------------------------------------------------------------------- */
     206             :     /*      Translate SRS.                                                  */
     207             :     /* -------------------------------------------------------------------- */
     208           3 :     const char *pszSRSName = poClass->GetSRSName();
     209           3 :     OGRSpatialReference *poSRS = nullptr;
     210           3 :     if (pszSRSName)
     211             :     {
     212           0 :         const char *pszHandle = strrchr(pszSRSName, ':');
     213           0 :         if (pszHandle != nullptr)
     214             :         {
     215           0 :             pszHandle += 1;
     216             : 
     217           0 :             poSRS = new OGRSpatialReference();
     218           0 :             poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     219             : 
     220           0 :             for (int i = 0; apszURNNames[i * 2 + 0] != nullptr; i++)
     221             :             {
     222           0 :                 const char *pszTarget = apszURNNames[i * 2 + 0];
     223           0 :                 const int nTLen = static_cast<int>(strlen(pszTarget));
     224             : 
     225             :                 // Are we just looking for a prefix match?
     226           0 :                 if (pszTarget[nTLen - 1] == '*')
     227             :                 {
     228           0 :                     if (EQUALN(pszTarget, pszHandle, nTLen - 1))
     229           0 :                         pszSRSName = apszURNNames[i * 2 + 1];
     230             :                 }
     231             :                 else
     232             :                 {
     233           0 :                     if (EQUAL(pszTarget, pszHandle))
     234           0 :                         pszSRSName = apszURNNames[i * 2 + 1];
     235             :                 }
     236             :             }
     237             : 
     238           0 :             if (poSRS->SetFromUserInput(
     239             :                     pszSRSName,
     240             :                     OGRSpatialReference::
     241           0 :                         SET_FROM_USER_INPUT_LIMITATIONS_get()) != OGRERR_NONE)
     242             :             {
     243           0 :                 CPLDebug("NAS", "Failed to translate srsName='%s'", pszSRSName);
     244           0 :                 delete poSRS;
     245           0 :                 poSRS = nullptr;
     246             :             }
     247             :         }
     248             :     }
     249             : 
     250             :     /* -------------------------------------------------------------------- */
     251             :     /*      Create an empty layer.                                          */
     252             :     /* -------------------------------------------------------------------- */
     253           3 :     OGRNASLayer *poLayer = new OGRNASLayer(poClass->GetName(), this);
     254             : 
     255             :     /* -------------------------------------------------------------------- */
     256             :     /*      Added attributes (properties).                                  */
     257             :     /* -------------------------------------------------------------------- */
     258          45 :     for (int iField = 0; iField < poClass->GetPropertyCount(); iField++)
     259             :     {
     260          42 :         GMLPropertyDefn *poProperty = poClass->GetProperty(iField);
     261             :         OGRFieldType eFType;
     262             : 
     263          42 :         if (poProperty->GetType() == GMLPT_Untyped)
     264           2 :             eFType = OFTString;
     265          40 :         else if (poProperty->GetType() == GMLPT_String)
     266          22 :             eFType = OFTString;
     267          18 :         else if (poProperty->GetType() == GMLPT_Integer)
     268          11 :             eFType = OFTInteger;
     269           7 :         else if (poProperty->GetType() == GMLPT_Real)
     270           1 :             eFType = OFTReal;
     271           6 :         else if (poProperty->GetType() == GMLPT_StringList)
     272           4 :             eFType = OFTStringList;
     273           2 :         else if (poProperty->GetType() == GMLPT_IntegerList)
     274           0 :             eFType = OFTIntegerList;
     275           2 :         else if (poProperty->GetType() == GMLPT_RealList)
     276           0 :             eFType = OFTRealList;
     277             :         else
     278           2 :             eFType = OFTString;
     279             : 
     280          84 :         OGRFieldDefn oField(poProperty->GetName(), eFType);
     281          42 :         if (STARTS_WITH_CI(oField.GetNameRef(), "ogr:"))
     282           0 :             oField.SetName(poProperty->GetName() + 4);
     283          42 :         if (poProperty->GetWidth() > 0)
     284          18 :             oField.SetWidth(poProperty->GetWidth());
     285             : 
     286          42 :         poLayer->GetLayerDefn()->AddFieldDefn(&oField);
     287             :     }
     288             : 
     289           4 :     for (int iField = 0; iField < poClass->GetGeometryPropertyCount(); iField++)
     290             :     {
     291             :         GMLGeometryPropertyDefn *poProperty =
     292           1 :             poClass->GetGeometryProperty(iField);
     293             :         OGRGeomFieldDefn oField(poProperty->GetName(),
     294           2 :                                 (OGRwkbGeometryType)poProperty->GetType());
     295           2 :         if (poClass->GetGeometryPropertyCount() == 1 &&
     296           1 :             poClass->GetFeatureCount() == 0)
     297             :         {
     298           0 :             oField.SetType(wkbUnknown);
     299             :         }
     300             : 
     301           1 :         oField.SetSpatialRef(poSRS);
     302           1 :         oField.SetNullable(poProperty->IsNullable());
     303           1 :         poLayer->GetLayerDefn()->AddGeomFieldDefn(&oField);
     304             :     }
     305             : 
     306           3 :     if (poSRS)
     307           0 :         poSRS->Dereference();
     308             : 
     309           3 :     return poLayer;
     310             : }
     311             : 
     312             : /************************************************************************/
     313             : /*                              GetLayer()                              */
     314             : /************************************************************************/
     315             : 
     316           4 : OGRLayer *OGRNASDataSource::GetLayer(int iLayer)
     317             : 
     318             : {
     319           4 :     if (iLayer < 0 || iLayer >= nLayers)
     320           0 :         return nullptr;
     321             : 
     322           4 :     return papoLayers[iLayer];
     323             : }
     324             : 
     325             : /************************************************************************/
     326             : /*                           TestCapability()                           */
     327             : /************************************************************************/
     328             : 
     329           0 : int OGRNASDataSource::TestCapability(const char * /* pszCap */)
     330             : {
     331           0 :     return FALSE;
     332             : }

Generated by: LCOV version 1.14