LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_edit.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 100 107 93.5 %
Date: 2025-06-19 12:30:01 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  "edit" step of "vector pipeline"
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_vector_edit.h"
      14             : 
      15             : #include "gdal_priv.h"
      16             : #include "gdal_utils.h"
      17             : 
      18             : //! @cond Doxygen_Suppress
      19             : 
      20             : #ifndef _
      21             : #define _(x) (x)
      22             : #endif
      23             : 
      24             : /************************************************************************/
      25             : /*          GDALVectorEditAlgorithm::GDALVectorEditAlgorithm()          */
      26             : /************************************************************************/
      27             : 
      28          29 : GDALVectorEditAlgorithm::GDALVectorEditAlgorithm(bool standaloneStep)
      29             :     : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
      30          29 :                                       standaloneStep)
      31             : {
      32          29 :     AddActiveLayerArg(&m_activeLayer);
      33          29 :     AddGeometryTypeArg(&m_geometryType, _("Layer geometry type"));
      34             : 
      35          58 :     AddArg("crs", 0, _("Override CRS (without reprojection)"), &m_overrideCrs)
      36          58 :         .AddHiddenAlias("a_srs")
      37          29 :         .SetIsCRSArg(/*noneAllowed=*/true);
      38             : 
      39             :     {
      40             :         auto &arg = AddArg("metadata", 0, _("Add/update dataset metadata item"),
      41          58 :                            &m_metadata)
      42          58 :                         .SetMetaVar("<KEY>=<VALUE>")
      43          29 :                         .SetPackedValuesAllowed(false);
      44           1 :         arg.AddValidationAction([this, &arg]()
      45          30 :                                 { return ParseAndValidateKeyValue(arg); });
      46          29 :         arg.AddHiddenAlias("mo");
      47             :     }
      48             : 
      49             :     AddArg("unset-metadata", 0, _("Remove dataset metadata item"),
      50          58 :            &m_unsetMetadata)
      51          29 :         .SetMetaVar("<KEY>");
      52             : 
      53             :     {
      54             :         auto &arg =
      55             :             AddArg("layer-metadata", 0, _("Add/update layer metadata item"),
      56          58 :                    &m_layerMetadata)
      57          58 :                 .SetMetaVar("<KEY>=<VALUE>")
      58          29 :                 .SetPackedValuesAllowed(false);
      59           2 :         arg.AddValidationAction([this, &arg]()
      60          31 :                                 { return ParseAndValidateKeyValue(arg); });
      61             :     }
      62             : 
      63             :     AddArg("unset-layer-metadata", 0, _("Remove layer metadata item"),
      64          58 :            &m_unsetLayerMetadata)
      65          29 :         .SetMetaVar("<KEY>");
      66          29 : }
      67             : 
      68             : /************************************************************************/
      69             : /*                   GDALVectorEditAlgorithmLayer                       */
      70             : /************************************************************************/
      71             : 
      72             : namespace
      73             : {
      74             : class GDALVectorEditAlgorithmLayer final : public GDALVectorPipelineOutputLayer
      75             : {
      76             :   public:
      77           7 :     GDALVectorEditAlgorithmLayer(
      78             :         OGRLayer &oSrcLayer, const std::string &activeLayer,
      79             :         bool bChangeGeomType, OGRwkbGeometryType eType,
      80             :         const std::string &overrideCrs,
      81             :         const std::vector<std::string> &layerMetadata,
      82             :         const std::vector<std::string> &unsetLayerMetadata)
      83           7 :         : GDALVectorPipelineOutputLayer(oSrcLayer),
      84           7 :           m_bOverrideCrs(!overrideCrs.empty())
      85             :     {
      86           7 :         SetDescription(oSrcLayer.GetDescription());
      87           7 :         SetMetadata(oSrcLayer.GetMetadata());
      88             : 
      89           7 :         m_poFeatureDefn = oSrcLayer.GetLayerDefn()->Clone();
      90           7 :         m_poFeatureDefn->Reference();
      91             : 
      92           7 :         if (activeLayer.empty() || activeLayer == GetDescription())
      93             :         {
      94          12 :             const CPLStringList aosMD(layerMetadata);
      95           8 :             for (const auto &[key, value] : cpl::IterateNameValue(aosMD))
      96             :             {
      97           2 :                 if (SetMetadataItem(key, value) != CE_None)
      98             :                 {
      99           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     100             :                              "SetMetadataItem('%s', '%s') failed", key, value);
     101             :                 }
     102             :             }
     103             : 
     104           7 :             for (const std::string &key : unsetLayerMetadata)
     105             :             {
     106           1 :                 if (SetMetadataItem(key.c_str(), nullptr) != CE_None)
     107             :                 {
     108           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     109             :                              "SetMetadataItem('%s', NULL) failed", key.c_str());
     110             :                 }
     111             :             }
     112             : 
     113           6 :             if (bChangeGeomType)
     114             :             {
     115           4 :                 for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
     116             :                 {
     117           2 :                     m_poFeatureDefn->GetGeomFieldDefn(i)->SetType(eType);
     118             :                 }
     119             :             }
     120             : 
     121           6 :             if (!overrideCrs.empty())
     122             :             {
     123           4 :                 if (!EQUAL(overrideCrs.c_str(), "null") &&
     124           2 :                     !EQUAL(overrideCrs.c_str(), "none"))
     125             :                 {
     126           1 :                     m_poSRS = new OGRSpatialReference();
     127           1 :                     m_poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     128           1 :                     m_poSRS->SetFromUserInput(overrideCrs.c_str());
     129             :                 }
     130           4 :                 for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
     131             :                 {
     132           2 :                     m_poFeatureDefn->GetGeomFieldDefn(i)->SetSpatialRef(
     133           2 :                         m_poSRS);
     134             :                 }
     135             :             }
     136             :         }
     137           7 :     }
     138             : 
     139          14 :     ~GDALVectorEditAlgorithmLayer()
     140           7 :     {
     141           7 :         m_poFeatureDefn->Release();
     142           7 :         if (m_poSRS)
     143           1 :             m_poSRS->Release();
     144          14 :     }
     145             : 
     146          82 :     OGRFeatureDefn *GetLayerDefn() override
     147             :     {
     148          82 :         return m_poFeatureDefn;
     149             :     }
     150             : 
     151          12 :     void TranslateFeature(
     152             :         std::unique_ptr<OGRFeature> poSrcFeature,
     153             :         std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
     154             :     {
     155          12 :         poSrcFeature->SetFDefnUnsafe(m_poFeatureDefn);
     156          12 :         if (m_bOverrideCrs)
     157             :         {
     158           4 :             for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
     159             :             {
     160           2 :                 auto poGeom = poSrcFeature->GetGeomFieldRef(i);
     161           2 :                 if (poGeom)
     162           2 :                     poGeom->assignSpatialReference(m_poSRS);
     163             :             }
     164             :         }
     165          12 :         apoOutFeatures.push_back(std::move(poSrcFeature));
     166          12 :     }
     167             : 
     168           8 :     int TestCapability(const char *pszCap) override
     169             :     {
     170           8 :         if (EQUAL(pszCap, OLCStringsAsUTF8) ||
     171           8 :             EQUAL(pszCap, OLCCurveGeometries) || EQUAL(pszCap, OLCZGeometries))
     172           0 :             return m_srcLayer.TestCapability(pszCap);
     173           8 :         return false;
     174             :     }
     175             : 
     176             :   private:
     177             :     const bool m_bOverrideCrs;
     178             :     OGRFeatureDefn *m_poFeatureDefn = nullptr;
     179             :     OGRSpatialReference *m_poSRS = nullptr;
     180             : 
     181             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorEditAlgorithmLayer)
     182             : };
     183             : 
     184             : }  // namespace
     185             : 
     186             : /************************************************************************/
     187             : /*                GDALVectorEditAlgorithm::RunStep()                    */
     188             : /************************************************************************/
     189             : 
     190           7 : bool GDALVectorEditAlgorithm::RunStep(GDALPipelineStepRunContext &)
     191             : {
     192           7 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
     193           7 :     CPLAssert(poSrcDS);
     194             : 
     195           7 :     CPLAssert(m_outputDataset.GetName().empty());
     196           7 :     CPLAssert(!m_outputDataset.GetDatasetRef());
     197             : 
     198           7 :     const int nLayerCount = poSrcDS->GetLayerCount();
     199             : 
     200           7 :     bool bChangeGeomType = false;
     201           7 :     OGRwkbGeometryType eType = wkbUnknown;
     202           7 :     if (!m_geometryType.empty())
     203             :     {
     204           2 :         eType = OGRFromOGCGeomType(m_geometryType.c_str());
     205           2 :         bChangeGeomType = true;
     206             :     }
     207             : 
     208          14 :     auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS);
     209             : 
     210          14 :     const CPLStringList aosMD(m_metadata);
     211           8 :     for (const auto &[key, value] : cpl::IterateNameValue(aosMD))
     212             :     {
     213           1 :         if (outDS->SetMetadataItem(key, value) != CE_None)
     214             :         {
     215           0 :             ReportError(CE_Failure, CPLE_AppDefined,
     216             :                         "SetMetadataItem('%s', '%s') failed", key, value);
     217           0 :             return false;
     218             :         }
     219             :     }
     220             : 
     221           8 :     for (const std::string &key : m_unsetMetadata)
     222             :     {
     223           1 :         if (outDS->SetMetadataItem(key.c_str(), nullptr) != CE_None)
     224             :         {
     225           0 :             ReportError(CE_Failure, CPLE_AppDefined,
     226             :                         "SetMetadataItem('%s', NULL) failed", key.c_str());
     227           0 :             return false;
     228             :         }
     229             :     }
     230             : 
     231           7 :     bool ret = true;
     232          14 :     for (int i = 0; ret && i < nLayerCount; ++i)
     233             :     {
     234           7 :         auto poSrcLayer = poSrcDS->GetLayer(i);
     235           7 :         ret = (poSrcLayer != nullptr);
     236           7 :         if (ret)
     237             :         {
     238          14 :             outDS->AddLayer(*poSrcLayer,
     239           7 :                             std::make_unique<GDALVectorEditAlgorithmLayer>(
     240           7 :                                 *poSrcLayer, m_activeLayer, bChangeGeomType,
     241           7 :                                 eType, m_overrideCrs, m_layerMetadata,
     242           7 :                                 m_unsetLayerMetadata));
     243             :         }
     244             :     }
     245             : 
     246           7 :     if (ret)
     247           7 :         m_outputDataset.Set(std::move(outDS));
     248             : 
     249           7 :     return ret;
     250             : }
     251             : 
     252             : GDALVectorEditAlgorithmStandalone::~GDALVectorEditAlgorithmStandalone() =
     253             :     default;
     254             : 
     255             : //! @endcond

Generated by: LCOV version 1.14