13#ifndef GDALALG_DISPATCHER_INCLUDED
14#define GDALALG_DISPATCHER_INCLUDED
16#include "gdalalgorithm.h"
27template <
class RasterDispatcher,
class VectorDispatcher>
31 GDALDispatcherAlgorithm(
const std::string &name,
32 const std::string &description,
33 const std::string &helpURL)
34 : GDALAlgorithm(name, description, helpURL),
35 m_rasterDispatcher(std::make_unique<RasterDispatcher>(
38 std::make_unique<VectorDispatcher>( true))
49 const UsageOptions &usageOptions)
const override;
52 std::unique_ptr<RasterDispatcher> m_rasterDispatcher{};
53 std::unique_ptr<VectorDispatcher> m_vectorDispatcher{};
54 bool m_showUsage =
true;
56 bool RunImpl(GDALProgressFunc,
void *)
override
59 "The Run() method should not be called directly on the \"gdal "
70template <
class RasterDispatcher,
class VectorDispatcher>
71bool GDALDispatcherAlgorithm<RasterDispatcher, VectorDispatcher>::
72 ParseCommandLineArguments(
const std::vector<std::string> &args)
74 if (args.size() == 1 && (args[0] ==
"-h" || args[0] ==
"--help"))
77 if (IsCalledFromCommandLine())
79 m_rasterDispatcher->SetCalledFromCommandLine();
80 m_vectorDispatcher->SetCalledFromCommandLine();
90 std::string osLastError;
96 ok = m_rasterDispatcher->ParseCommandLineArguments(args);
105 ok = m_rasterDispatcher->ParseCommandLineArguments(args);
108 if (m_rasterDispatcher->PropagateSpecialActionTo(
this))
115 auto poDS = m_rasterDispatcher->GetInputDatasetRef();
118 (poDS->GetRasterCount() > 0 || poDS->GetMetadata(
"SUBDATASETS")))
120 if (poDS->GetLayerCount() != 0)
124 "'%s' has both raster and vector content. "
125 "Please use 'gdal raster %s' or 'gdal vector %s'.",
126 poDS->GetDescription(), GetName().c_str(),
131 m_selectedSubAlg = m_rasterDispatcher.get();
132 std::vector<std::string> callPath(m_callPath);
133 callPath.push_back(
"raster");
134 m_selectedSubAlg->SetCallPath(callPath);
139 else if (args.size() <= 1)
144 auto poDSFromRaster = m_rasterDispatcher->GetInputDatasetRef();
148 m_vectorDispatcher->SetInputDataset(poDSFromRaster);
151 std::vector<std::string> argsWithoutInput;
152 bool skipNext =
false;
153 std::string osLikelyDatasetName;
154 size_t nCountLikelyDatasetName = 0;
155 for (
const auto &arg : args)
157 if (arg ==
"-i" || arg ==
"--input")
164 !(poDSFromRaster && arg == poDSFromRaster->GetDescription()))
166 if (!arg.empty() && arg[0] !=
'-')
168 ++nCountLikelyDatasetName;
169 osLikelyDatasetName = arg;
171 argsWithoutInput.push_back(arg);
182 ok = m_vectorDispatcher->ParseCommandLineArguments(argsWithoutInput);
186 m_selectedSubAlg = m_vectorDispatcher.get();
187 std::vector<std::string> callPath(m_callPath);
188 callPath.push_back(
"vector");
189 m_selectedSubAlg->SetCallPath(callPath);
195 bool managedToOpenDS =
false;
196 for (
const auto &arg : args)
199 if (
VSIStatL(arg.c_str(), &sStat) == 0)
205 managedToOpenDS =
true;
206 if (poDS->GetRasterCount() > 0 ||
207 poDS->GetMetadata(
"SUBDATASETS"))
209 if (poDS->GetLayerCount() != 0)
213 "'%s' has both raster and vector content. "
214 "Please use 'gdal raster %s' or 'gdal "
216 poDS->GetDescription(), GetName().c_str(),
220 m_rasterDispatcher = std::make_unique<RasterDispatcher>();
221 auto poDSRaw = poDS.get();
222 m_rasterDispatcher->SetInputDataset(poDS.release());
224 m_selectedSubAlg = m_rasterDispatcher.get();
225 std::vector<std::string> callPath(m_callPath);
226 callPath.push_back(
"raster");
227 m_selectedSubAlg->SetCallPath(callPath);
228 ret = m_selectedSubAlg->ParseCommandLineArguments(
231 else if (poDS->GetLayerCount() != 0)
233 m_vectorDispatcher = std::make_unique<VectorDispatcher>();
234 auto poDSRaw = poDS.get();
235 m_vectorDispatcher->SetInputDataset(poDS.release());
237 m_selectedSubAlg = m_vectorDispatcher.get();
238 std::vector<std::string> callPath(m_callPath);
239 callPath.push_back(
"vector");
240 m_selectedSubAlg->SetCallPath(callPath);
241 ret = m_selectedSubAlg->ParseCommandLineArguments(
249 if (!ret && !managedToOpenDS &&
250 (osLastError.find(
"not recognized") != std::string::npos ||
251 (nCountLikelyDatasetName == 1 &&
252 cpl::starts_with(osLastError, osLikelyDatasetName))))
264template <
class RasterDispatcher,
class VectorDispatcher>
266GDALDispatcherAlgorithm<RasterDispatcher, VectorDispatcher>::GetUsageForCLI(
267 bool shortUsage,
const UsageOptions &usageOptions)
const
269 if (m_selectedSubAlg)
271 return m_selectedSubAlg->GetUsageForCLI(shortUsage, usageOptions);
277 return std::string();
Class that saves the error state on construction, and restores it on destruction.
Definition cpl_error.h:410
GDAL algorithm.
Definition gdalalgorithm_cpp.h:2261
virtual std::string GetUsageForCLI(bool shortUsage, const UsageOptions &usageOptions=UsageOptions()) const
Return the usage as a string appropriate for command-line interface --help output.
Definition gdalalgorithm.cpp:5909
virtual bool ParseCommandLineArguments(const std::vector< std::string > &args)
Parse a command line argument, which does not include the algorithm name, to set the value of corresp...
Definition gdalalgorithm.cpp:2003
const std::string & GetName() const
Get the algorithm name.
Definition gdalalgorithm_cpp.h:2268
void SetDisplayInJSONUsage(bool b)
Set whether this algorithm should be reported in JSON usage.
Definition gdalalgorithm_cpp.h:2970
static GDALDataset * Open(const char *pszFilename, unsigned int nOpenFlags=0, const char *const *papszAllowedDrivers=nullptr, const char *const *papszOpenOptions=nullptr, const char *const *papszSiblingFiles=nullptr)
Definition gdal_dataset.h:554
CPL error handling services.
GUInt32 CPLGetErrorCounter(void)
Get the error counter.
Definition cpl_error.cpp:981
#define CPLE_AppDefined
Application defined error.
Definition cpl_error.h:85
const char * CPLGetLastErrorMsg(void)
Get the last error message.
Definition cpl_error.cpp:959
CPLErr CPLGetLastErrorType(void)
Fetch the last error type.
Definition cpl_error.cpp:935
#define STARTS_WITH(a, b)
Returns whether a starts with b.
Definition cpl_port.h:550
#define VSIStatBufL
Type for VSIStatL().
Definition cpl_vsi.h:195
int VSIStatL(const char *, VSIStatBufL *)
Get filesystem object info.
Definition cpl_vsil.cpp:1547
This file is legacy since GDAL 3.12, but will be kept at least in the whole GDAL 3....