LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_edit.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 105 123 85.4 %
Date: 2025-05-15 13:16:46 Functions: 10 11 90.9 %

          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          14 : GDALVectorEditAlgorithm::GDALVectorEditAlgorithm(bool standaloneStep)
      29             :     : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
      30          14 :                                       standaloneStep)
      31             : {
      32          14 :     AddActiveLayerArg(&m_activeLayer);
      33          28 :     AddArg("geometry-type", 0, _("Layer geometry type"), &m_geometryType)
      34             :         .SetAutoCompleteFunction(
      35           0 :             [](const std::string &currentValue)
      36             :             {
      37           0 :                 std::vector<std::string> oRet;
      38           0 :                 for (const char *type :
      39             :                      {"GEOMETRY", "POINT", "LINESTRING", "POLYGON",
      40             :                       "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON",
      41             :                       "GEOMETRYCOLLECTION", "CURVE", "CIRCULARSTRING",
      42             :                       "COMPOUNDCURVE", "SURFACE", "CURVEPOLYGON", "MULTICURVE",
      43           0 :                       "MULTISURFACE", "POLYHEDRALSURFACE", "TIN"})
      44             :                 {
      45           0 :                     if (currentValue.empty() ||
      46           0 :                         STARTS_WITH(type, currentValue.c_str()))
      47             :                     {
      48           0 :                         oRet.push_back(type);
      49           0 :                         oRet.push_back(std::string(type).append("Z"));
      50           0 :                         oRet.push_back(std::string(type).append("M"));
      51           0 :                         oRet.push_back(std::string(type).append("ZM"));
      52             :                     }
      53             :                 }
      54           0 :                 return oRet;
      55          14 :             });
      56             : 
      57          28 :     AddArg("crs", 0, _("Override CRS (without reprojection)"), &m_overrideCrs)
      58          28 :         .AddHiddenAlias("a_srs")
      59          14 :         .SetIsCRSArg(/*noneAllowed=*/true);
      60             : 
      61             :     {
      62             :         auto &arg = AddArg("metadata", 0, _("Add/update dataset metadata item"),
      63          28 :                            &m_metadata)
      64          28 :                         .SetMetaVar("<KEY>=<VALUE>")
      65          14 :                         .SetPackedValuesAllowed(false);
      66           1 :         arg.AddValidationAction([this, &arg]()
      67          15 :                                 { return ParseAndValidateKeyValue(arg); });
      68          14 :         arg.AddHiddenAlias("mo");
      69             :     }
      70             : 
      71             :     AddArg("unset-metadata", 0, _("Remove dataset metadata item"),
      72          28 :            &m_unsetMetadata)
      73          14 :         .SetMetaVar("<KEY>");
      74             : 
      75             :     {
      76             :         auto &arg =
      77             :             AddArg("layer-metadata", 0, _("Add/update layer metadata item"),
      78          28 :                    &m_layerMetadata)
      79          28 :                 .SetMetaVar("<KEY>=<VALUE>")
      80          14 :                 .SetPackedValuesAllowed(false);
      81           1 :         arg.AddValidationAction([this, &arg]()
      82          15 :                                 { return ParseAndValidateKeyValue(arg); });
      83             :     }
      84             : 
      85             :     AddArg("unset-layer-metadata", 0, _("Remove layer metadata item"),
      86          28 :            &m_unsetLayerMetadata)
      87          14 :         .SetMetaVar("<KEY>");
      88          14 : }
      89             : 
      90             : /************************************************************************/
      91             : /*                   GDALVectorEditAlgorithmLayer                       */
      92             : /************************************************************************/
      93             : 
      94             : namespace
      95             : {
      96             : class GDALVectorEditAlgorithmLayer final : public GDALVectorPipelineOutputLayer
      97             : {
      98             :   public:
      99           6 :     GDALVectorEditAlgorithmLayer(
     100             :         OGRLayer &oSrcLayer, const std::string &activeLayer,
     101             :         bool bChangeGeomType, OGRwkbGeometryType eType,
     102             :         const std::string &overrideCrs,
     103             :         const std::vector<std::string> &layerMetadata,
     104             :         const std::vector<std::string> &unsetLayerMetadata)
     105           6 :         : GDALVectorPipelineOutputLayer(oSrcLayer),
     106           6 :           m_bOverrideCrs(!overrideCrs.empty())
     107             :     {
     108           6 :         SetDescription(oSrcLayer.GetDescription());
     109           6 :         SetMetadata(oSrcLayer.GetMetadata());
     110             : 
     111           6 :         m_poFeatureDefn = oSrcLayer.GetLayerDefn()->Clone();
     112           6 :         m_poFeatureDefn->Reference();
     113             : 
     114           6 :         if (activeLayer.empty() || activeLayer == GetDescription())
     115             :         {
     116          10 :             const CPLStringList aosMD(layerMetadata);
     117           6 :             for (const auto &[key, value] : cpl::IterateNameValue(aosMD))
     118             :             {
     119           1 :                 if (SetMetadataItem(key, value) != CE_None)
     120             :                 {
     121           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     122             :                              "SetMetadataItem('%s', '%s') failed", key, value);
     123             :                 }
     124             :             }
     125             : 
     126           6 :             for (const std::string &key : unsetLayerMetadata)
     127             :             {
     128           1 :                 if (SetMetadataItem(key.c_str(), nullptr) != CE_None)
     129             :                 {
     130           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     131             :                              "SetMetadataItem('%s', NULL) failed", key.c_str());
     132             :                 }
     133             :             }
     134             : 
     135           5 :             if (bChangeGeomType)
     136             :             {
     137           4 :                 for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
     138             :                 {
     139           2 :                     m_poFeatureDefn->GetGeomFieldDefn(i)->SetType(eType);
     140             :                 }
     141             :             }
     142             : 
     143           5 :             if (!overrideCrs.empty())
     144             :             {
     145           4 :                 if (!EQUAL(overrideCrs.c_str(), "null") &&
     146           2 :                     !EQUAL(overrideCrs.c_str(), "none"))
     147             :                 {
     148           1 :                     m_poSRS = new OGRSpatialReference();
     149           1 :                     m_poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     150           1 :                     m_poSRS->SetFromUserInput(overrideCrs.c_str());
     151             :                 }
     152           4 :                 for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
     153             :                 {
     154           2 :                     m_poFeatureDefn->GetGeomFieldDefn(i)->SetSpatialRef(
     155           2 :                         m_poSRS);
     156             :                 }
     157             :             }
     158             :         }
     159           6 :     }
     160             : 
     161          12 :     ~GDALVectorEditAlgorithmLayer()
     162           6 :     {
     163           6 :         m_poFeatureDefn->Release();
     164           6 :         if (m_poSRS)
     165           1 :             m_poSRS->Release();
     166          12 :     }
     167             : 
     168          72 :     OGRFeatureDefn *GetLayerDefn() override
     169             :     {
     170          72 :         return m_poFeatureDefn;
     171             :     }
     172             : 
     173           2 :     void TranslateFeature(
     174             :         std::unique_ptr<OGRFeature> poSrcFeature,
     175             :         std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
     176             :     {
     177           2 :         poSrcFeature->SetFDefnUnsafe(m_poFeatureDefn);
     178           2 :         if (m_bOverrideCrs)
     179             :         {
     180           4 :             for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
     181             :             {
     182           2 :                 auto poGeom = poSrcFeature->GetGeomFieldRef(i);
     183           2 :                 if (poGeom)
     184           2 :                     poGeom->assignSpatialReference(m_poSRS);
     185             :             }
     186             :         }
     187           2 :         apoOutFeatures.push_back(std::move(poSrcFeature));
     188           2 :     }
     189             : 
     190           6 :     int TestCapability(const char *pszCap) override
     191             :     {
     192           6 :         if (EQUAL(pszCap, OLCStringsAsUTF8) ||
     193           6 :             EQUAL(pszCap, OLCCurveGeometries) || EQUAL(pszCap, OLCZGeometries))
     194           0 :             return m_srcLayer.TestCapability(pszCap);
     195           6 :         return false;
     196             :     }
     197             : 
     198             :   private:
     199             :     const bool m_bOverrideCrs;
     200             :     OGRFeatureDefn *m_poFeatureDefn = nullptr;
     201             :     OGRSpatialReference *m_poSRS = nullptr;
     202             : 
     203             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorEditAlgorithmLayer)
     204             : };
     205             : 
     206             : }  // namespace
     207             : 
     208             : /************************************************************************/
     209             : /*                GDALVectorEditAlgorithm::RunStep()                    */
     210             : /************************************************************************/
     211             : 
     212           7 : bool GDALVectorEditAlgorithm::RunStep(GDALProgressFunc, void *)
     213             : {
     214           7 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
     215           7 :     CPLAssert(poSrcDS);
     216             : 
     217           7 :     CPLAssert(m_outputDataset.GetName().empty());
     218           7 :     CPLAssert(!m_outputDataset.GetDatasetRef());
     219             : 
     220           7 :     const int nLayerCount = poSrcDS->GetLayerCount();
     221             : 
     222           7 :     bool bChangeGeomType = false;
     223           7 :     OGRwkbGeometryType eType = wkbUnknown;
     224           7 :     if (!m_geometryType.empty())
     225             :     {
     226           3 :         eType = OGRFromOGCGeomType(m_geometryType.c_str());
     227           5 :         if (wkbFlatten(eType) == wkbUnknown &&
     228           2 :             !STARTS_WITH_CI(m_geometryType.c_str(), "GEOMETRY"))
     229             :         {
     230           1 :             ReportError(CE_Failure, CPLE_AppDefined,
     231             :                         "Invalid geometry type '%s'", m_geometryType.c_str());
     232           1 :             return false;
     233             :         }
     234           2 :         bChangeGeomType = true;
     235             :     }
     236             : 
     237          12 :     auto outDS = std::make_unique<GDALVectorPipelineOutputDataset>(*poSrcDS);
     238             : 
     239          12 :     const CPLStringList aosMD(m_metadata);
     240           7 :     for (const auto &[key, value] : cpl::IterateNameValue(aosMD))
     241             :     {
     242           1 :         if (outDS->SetMetadataItem(key, value) != CE_None)
     243             :         {
     244           0 :             ReportError(CE_Failure, CPLE_AppDefined,
     245             :                         "SetMetadataItem('%s', '%s') failed", key, value);
     246           0 :             return false;
     247             :         }
     248             :     }
     249             : 
     250           7 :     for (const std::string &key : m_unsetMetadata)
     251             :     {
     252           1 :         if (outDS->SetMetadataItem(key.c_str(), nullptr) != CE_None)
     253             :         {
     254           0 :             ReportError(CE_Failure, CPLE_AppDefined,
     255             :                         "SetMetadataItem('%s', NULL) failed", key.c_str());
     256           0 :             return false;
     257             :         }
     258             :     }
     259             : 
     260           6 :     bool ret = true;
     261          12 :     for (int i = 0; ret && i < nLayerCount; ++i)
     262             :     {
     263           6 :         auto poSrcLayer = poSrcDS->GetLayer(i);
     264           6 :         ret = (poSrcLayer != nullptr);
     265           6 :         if (ret)
     266             :         {
     267          12 :             outDS->AddLayer(*poSrcLayer,
     268           6 :                             std::make_unique<GDALVectorEditAlgorithmLayer>(
     269           6 :                                 *poSrcLayer, m_activeLayer, bChangeGeomType,
     270           6 :                                 eType, m_overrideCrs, m_layerMetadata,
     271           6 :                                 m_unsetLayerMetadata));
     272             :         }
     273             :     }
     274             : 
     275           6 :     if (ret)
     276           6 :         m_outputDataset.Set(std::move(outDS));
     277             : 
     278           6 :     return ret;
     279             : }
     280             : 
     281             : //! @endcond

Generated by: LCOV version 1.14