/src/gdal/apps/gdalpipelinestepalgorithm.h
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: GDAL |
4 | | * Purpose: gdal "raster/vector pipeline" subcommand |
5 | | * Author: Even Rouault <even dot rouault at spatialys.com> |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #ifndef GDALPIPELINESTEPALGORITHM_INCLUDED |
14 | | #define GDALPIPELINESTEPALGORITHM_INCLUDED |
15 | | |
16 | | //! @cond Doxygen_Suppress |
17 | | |
18 | | #include "gdalalgorithm.h" |
19 | | |
20 | | #include "gdalpipelinestepruncontext.h" |
21 | | |
22 | | /************************************************************************/ |
23 | | /* GDALPipelineStepAlgorithm */ |
24 | | /************************************************************************/ |
25 | | |
26 | | class OGRLayer; |
27 | | |
28 | | class GDALPipelineStepAlgorithm /* non final */ : public GDALAlgorithm |
29 | | { |
30 | | public: |
31 | | std::vector<GDALArgDatasetValue> &GetInputDatasets() |
32 | 0 | { |
33 | 0 | return m_inputDataset; |
34 | 0 | } |
35 | | |
36 | | const std::vector<GDALArgDatasetValue> &GetInputDatasets() const |
37 | 0 | { |
38 | 0 | return m_inputDataset; |
39 | 0 | } |
40 | | |
41 | | GDALArgDatasetValue &GetOutputDataset() |
42 | 0 | { |
43 | 0 | return m_outputDataset; |
44 | 0 | } |
45 | | |
46 | | const GDALArgDatasetValue &GetOutputDataset() const |
47 | 0 | { |
48 | 0 | return m_outputDataset; |
49 | 0 | } |
50 | | |
51 | | const std::string &GetOutputString() const |
52 | 0 | { |
53 | 0 | return m_output; |
54 | 0 | } |
55 | | |
56 | | const std::string &GetOutputLayerName() const |
57 | 0 | { |
58 | 0 | return m_outputLayerName; |
59 | 0 | } |
60 | | |
61 | | const std::string &GetOutputFormat() const |
62 | 0 | { |
63 | 0 | return m_format; |
64 | 0 | } |
65 | | |
66 | | const std::vector<std::string> &GetCreationOptions() const |
67 | 0 | { |
68 | 0 | return m_creationOptions; |
69 | 0 | } |
70 | | |
71 | | const std::vector<std::string> &GetLayerCreationOptions() const |
72 | 0 | { |
73 | 0 | return m_layerCreationOptions; |
74 | 0 | } |
75 | | |
76 | | bool GetOverwriteLayer() const |
77 | 0 | { |
78 | 0 | return m_overwriteLayer; |
79 | 0 | } |
80 | | |
81 | | bool GetAppendLayer() const |
82 | 0 | { |
83 | 0 | return m_appendLayer; |
84 | 0 | } |
85 | | |
86 | | virtual int GetInputType() const = 0; |
87 | | |
88 | | virtual int GetOutputType() const = 0; |
89 | | |
90 | | bool Finalize() override; |
91 | | |
92 | | // Used by GDALDispatcherAlgorithm for vector info/convert |
93 | | GDALDataset *GetInputDatasetRef() |
94 | 0 | { |
95 | 0 | return m_inputDataset.empty() ? nullptr |
96 | 0 | : m_inputDataset[0].GetDatasetRef(); |
97 | 0 | } |
98 | | |
99 | | // Used by GDALDispatcherAlgorithm for vector info/convert |
100 | | void SetInputDataset(GDALDataset *poDS); |
101 | | |
102 | | protected: |
103 | | struct ConstructorOptions |
104 | | { |
105 | | bool standaloneStep = false; |
106 | | bool addDefaultArguments = true; |
107 | | bool autoOpenInputDatasets = true; |
108 | | bool inputDatasetRequired = true; |
109 | | bool inputDatasetPositional = true; |
110 | | bool outputDatasetRequired = true; |
111 | | bool addInputLayerNameArgument = true; // only for vector input |
112 | | bool addUpdateArgument = true; // only for vector output |
113 | | bool addAppendLayerArgument = true; // only for vector output |
114 | | bool addNoCreateEmptyLayersArgument = false; // only for vector output |
115 | | bool addOverwriteLayerArgument = true; // only for vector output |
116 | | bool addUpsertArgument = true; // only for vector output |
117 | | bool addSkipErrorsArgument = true; // only for vector output |
118 | | bool addOutputLayerNameArgument = true; // only for vector output |
119 | | bool outputLayerNameAvailableInPipelineStep = false; |
120 | | int inputDatasetMaxCount = 1; |
121 | | int inputDatasetInputFlags = GADV_NAME | GADV_OBJECT; |
122 | | std::string inputDatasetHelpMsg{}; |
123 | | std::string inputDatasetAlias{}; |
124 | | std::string inputDatasetMetaVar = "INPUT"; |
125 | | std::string outputDatasetHelpMsg{}; |
126 | | std::string outputFormatCreateCapability = GDAL_DCAP_CREATECOPY; |
127 | | bool mdimOutputAcceptsClassicRaster = false; // only for mdim output |
128 | | |
129 | | inline ConstructorOptions &SetStandaloneStep(bool b) |
130 | 0 | { |
131 | 0 | standaloneStep = b; |
132 | 0 | return *this; |
133 | 0 | } |
134 | | |
135 | | inline ConstructorOptions &SetAddDefaultArguments(bool b) |
136 | 0 | { |
137 | 0 | addDefaultArguments = b; |
138 | 0 | return *this; |
139 | 0 | } |
140 | | |
141 | | inline ConstructorOptions &SetAddInputLayerNameArgument(bool b) |
142 | 0 | { |
143 | 0 | addInputLayerNameArgument = b; |
144 | 0 | return *this; |
145 | 0 | } |
146 | | |
147 | | inline ConstructorOptions &SetInputDatasetRequired(bool b) |
148 | 0 | { |
149 | 0 | inputDatasetRequired = b; |
150 | 0 | return *this; |
151 | 0 | } |
152 | | |
153 | | inline ConstructorOptions &SetInputDatasetPositional(bool b) |
154 | 0 | { |
155 | 0 | inputDatasetPositional = b; |
156 | 0 | return *this; |
157 | 0 | } |
158 | | |
159 | | inline ConstructorOptions &SetInputDatasetMaxCount(int maxCount) |
160 | 0 | { |
161 | 0 | inputDatasetMaxCount = maxCount; |
162 | 0 | return *this; |
163 | 0 | } |
164 | | |
165 | | inline ConstructorOptions &SetInputDatasetInputFlags(int flags) |
166 | 0 | { |
167 | 0 | inputDatasetInputFlags = flags; |
168 | 0 | return *this; |
169 | 0 | } |
170 | | |
171 | | inline ConstructorOptions &SetInputDatasetHelpMsg(const std::string &s) |
172 | 0 | { |
173 | 0 | inputDatasetHelpMsg = s; |
174 | 0 | return *this; |
175 | 0 | } |
176 | | |
177 | | inline ConstructorOptions &SetInputDatasetAlias(const std::string &s) |
178 | 0 | { |
179 | 0 | inputDatasetAlias = s; |
180 | 0 | return *this; |
181 | 0 | } |
182 | | |
183 | | inline ConstructorOptions &SetInputDatasetMetaVar(const std::string &s) |
184 | 0 | { |
185 | 0 | inputDatasetMetaVar = s; |
186 | 0 | return *this; |
187 | 0 | } |
188 | | |
189 | | inline ConstructorOptions &SetOutputDatasetHelpMsg(const std::string &s) |
190 | 0 | { |
191 | 0 | outputDatasetHelpMsg = s; |
192 | 0 | return *this; |
193 | 0 | } |
194 | | |
195 | | inline ConstructorOptions &SetAutoOpenInputDatasets(bool b) |
196 | 0 | { |
197 | 0 | autoOpenInputDatasets = b; |
198 | 0 | return *this; |
199 | 0 | } |
200 | | |
201 | | inline ConstructorOptions &SetOutputDatasetRequired(bool b) |
202 | 0 | { |
203 | 0 | outputDatasetRequired = b; |
204 | 0 | return *this; |
205 | 0 | } |
206 | | |
207 | | inline ConstructorOptions & |
208 | | SetOutputFormatCreateCapability(const std::string &capability) |
209 | 0 | { |
210 | 0 | outputFormatCreateCapability = capability; |
211 | 0 | return *this; |
212 | 0 | } |
213 | | |
214 | | /** Whether the output format of a multidimensional algorithm may also |
215 | | * be a classic raster driver, which is the case of algorithms whose |
216 | | * output is written by GDALMultiDimTranslate(). */ |
217 | | inline ConstructorOptions &SetMdimOutputAcceptsClassicRaster(bool b) |
218 | 0 | { |
219 | 0 | mdimOutputAcceptsClassicRaster = b; |
220 | 0 | return *this; |
221 | 0 | } |
222 | | |
223 | | inline ConstructorOptions &SetAddAppendLayerArgument(bool b) |
224 | 0 | { |
225 | 0 | addAppendLayerArgument = b; |
226 | 0 | return *this; |
227 | 0 | } |
228 | | |
229 | | inline ConstructorOptions &SetAddOverwriteLayerArgument(bool b) |
230 | 0 | { |
231 | 0 | addOverwriteLayerArgument = b; |
232 | 0 | return *this; |
233 | 0 | } |
234 | | |
235 | | inline ConstructorOptions &SetAddUpdateArgument(bool b) |
236 | 0 | { |
237 | 0 | addUpdateArgument = b; |
238 | 0 | return *this; |
239 | 0 | } |
240 | | |
241 | | inline ConstructorOptions &SetAddUpsertArgument(bool b) |
242 | 0 | { |
243 | 0 | addUpsertArgument = b; |
244 | 0 | return *this; |
245 | 0 | } |
246 | | |
247 | | inline ConstructorOptions &SetNoCreateEmptyLayersArgument(bool b) |
248 | 0 | { |
249 | 0 | addNoCreateEmptyLayersArgument = b; |
250 | 0 | return *this; |
251 | 0 | } |
252 | | |
253 | | inline ConstructorOptions &SetAddSkipErrorsArgument(bool b) |
254 | 0 | { |
255 | 0 | addSkipErrorsArgument = b; |
256 | 0 | return *this; |
257 | 0 | } |
258 | | |
259 | | inline ConstructorOptions &SetAddOutputLayerNameArgument(bool b) |
260 | 0 | { |
261 | 0 | addOutputLayerNameArgument = b; |
262 | 0 | return *this; |
263 | 0 | } |
264 | | |
265 | | inline ConstructorOptions & |
266 | | SetOutputLayerNameAvailableInPipelineStep(bool b) |
267 | 0 | { |
268 | 0 | outputLayerNameAvailableInPipelineStep = b; |
269 | 0 | return *this; |
270 | 0 | } |
271 | | }; |
272 | | |
273 | | GDALPipelineStepAlgorithm(const std::string &name, |
274 | | const std::string &description, |
275 | | const std::string &helpURL, |
276 | | const ConstructorOptions &); |
277 | | |
278 | | friend class GDALPipelineAlgorithm; |
279 | | friend class GDALRasterPipelineAlgorithm; |
280 | | friend class GDALVectorPipelineAlgorithm; |
281 | | friend class GDALMdimPipelineAlgorithm; |
282 | | friend class GDALAbstractPipelineAlgorithm; |
283 | | |
284 | | virtual bool CanBeFirstStep() const |
285 | 0 | { |
286 | 0 | return false; |
287 | 0 | } |
288 | | |
289 | | virtual bool CanBeMiddleStep() const |
290 | 0 | { |
291 | 0 | return !CanBeFirstStep() && !CanBeLastStep(); |
292 | 0 | } |
293 | | |
294 | | virtual bool CanBeLastStep() const |
295 | 0 | { |
296 | 0 | return false; |
297 | 0 | } |
298 | | |
299 | | //! Whether a user parameter can cause a file to be written at a specified location |
300 | | virtual bool GeneratesFilesFromUserInput() const |
301 | 0 | { |
302 | 0 | return false; |
303 | 0 | } |
304 | | |
305 | | virtual bool IsNativelyStreamingCompatible() const |
306 | 0 | { |
307 | 0 | return true; |
308 | 0 | } |
309 | | |
310 | | virtual bool SupportsInputMultiThreading() const |
311 | 0 | { |
312 | 0 | return false; |
313 | 0 | } |
314 | | |
315 | | virtual bool CanHandleNextStep(GDALPipelineStepAlgorithm *) const |
316 | 0 | { |
317 | 0 | return false; |
318 | 0 | } |
319 | | |
320 | | virtual bool OutputDatasetAllowedBeforeRunningStep() const |
321 | 0 | { |
322 | 0 | return false; |
323 | 0 | } |
324 | | |
325 | | virtual CPLJSONObject Get_OGR_SCHEMA_OpenOption_Layer() const |
326 | 0 | { |
327 | 0 | CPLJSONObject obj; |
328 | 0 | obj.Deinit(); |
329 | 0 | return obj; |
330 | 0 | } |
331 | | |
332 | | virtual bool RunStep(GDALPipelineStepRunContext &ctxt) = 0; |
333 | | |
334 | | bool m_standaloneStep = false; |
335 | | const ConstructorOptions m_constructorOptions; |
336 | | bool m_outputVRTCompatible = true; |
337 | | std::string m_helpDocCategory{}; |
338 | | |
339 | | // Input arguments |
340 | | std::vector<GDALArgDatasetValue> m_inputDataset{}; |
341 | | std::vector<std::string> m_openOptions{}; |
342 | | std::vector<std::string> m_inputFormats{}; |
343 | | std::vector<std::string> m_inputLayerNames{}; |
344 | | |
345 | | // Output arguments |
346 | | bool m_stdout = false; |
347 | | std::string m_output{}; |
348 | | GDALArgDatasetValue m_outputDataset{}; |
349 | | std::string m_format{}; |
350 | | std::vector<std::string> m_outputOpenOptions{}; |
351 | | std::vector<std::string> m_creationOptions{}; |
352 | | bool m_overwrite = false; |
353 | | std::string m_outputLayerName{}; |
354 | | GDALInConstructionAlgorithmArg *m_outputFormatArg = nullptr; |
355 | | bool m_appendRaster = false; |
356 | | |
357 | | // Output arguments (vector specific) |
358 | | std::vector<std::string> m_layerCreationOptions{}; |
359 | | bool m_update = false; |
360 | | bool m_overwriteLayer = false; |
361 | | bool m_appendLayer = false; |
362 | | bool m_upsert = false; |
363 | | bool m_skipErrors = false; |
364 | | bool m_noCreateEmptyLayers = false; |
365 | | |
366 | | void AddRasterInputArgs(bool openForMixedRasterVector, bool hiddenForCLI); |
367 | | void AddRasterOutputArgs(bool hiddenForCLI); |
368 | | void AddRasterHiddenInputDatasetArg(); |
369 | | |
370 | | void AddVectorInputArgs(bool hiddenForCLI); |
371 | | void AddVectorHiddenInputDatasetArg(); |
372 | | void AddVectorOutputArgs(bool hiddenForCLI, |
373 | | bool shortNameOutputLayerAllowed); |
374 | | using GDALAlgorithm::AddOutputLayerNameArg; |
375 | | void AddOutputLayerNameArg(bool hiddenForCLI, |
376 | | bool shortNameOutputLayerAllowed); |
377 | | |
378 | | void AddMdimInputArgs(bool openForMixedRasterVector, bool hiddenForCLI, |
379 | | bool acceptRaster); |
380 | | void AddMdimOutputArgs(bool hiddenForCLI); |
381 | | void AddMdimHiddenInputDatasetArg(); |
382 | | |
383 | | bool CreateDatasetSingleOutputLayerIfNeeded( |
384 | | GDALPipelineStepRunContext &ctxt, const std::string &defaultLayerName, |
385 | | GDALDataset *&poDstDS, bool &bTemporaryFile, |
386 | | std::unique_ptr<GDALDataset> &poNewRetDS, std::string &outputLayerName, |
387 | | OGRLayer *&poDstLayer); |
388 | | |
389 | | private: |
390 | | bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override; |
391 | | GDALAlgorithm::ProcessGDALGOutputRet ProcessGDALGOutput() override; |
392 | | bool CheckSafeForStreamOutput() override; |
393 | | |
394 | | CPL_DISALLOW_COPY_ASSIGN(GDALPipelineStepAlgorithm) |
395 | | }; |
396 | | |
397 | | //! @endcond |
398 | | |
399 | | #endif |