/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 | | |
128 | | inline ConstructorOptions &SetStandaloneStep(bool b) |
129 | 0 | { |
130 | 0 | standaloneStep = b; |
131 | 0 | return *this; |
132 | 0 | } |
133 | | |
134 | | inline ConstructorOptions &SetAddDefaultArguments(bool b) |
135 | 0 | { |
136 | 0 | addDefaultArguments = b; |
137 | 0 | return *this; |
138 | 0 | } |
139 | | |
140 | | inline ConstructorOptions &SetAddInputLayerNameArgument(bool b) |
141 | 0 | { |
142 | 0 | addInputLayerNameArgument = b; |
143 | 0 | return *this; |
144 | 0 | } |
145 | | |
146 | | inline ConstructorOptions &SetInputDatasetRequired(bool b) |
147 | 0 | { |
148 | 0 | inputDatasetRequired = b; |
149 | 0 | return *this; |
150 | 0 | } |
151 | | |
152 | | inline ConstructorOptions &SetInputDatasetPositional(bool b) |
153 | 0 | { |
154 | 0 | inputDatasetPositional = b; |
155 | 0 | return *this; |
156 | 0 | } |
157 | | |
158 | | inline ConstructorOptions &SetInputDatasetMaxCount(int maxCount) |
159 | 0 | { |
160 | 0 | inputDatasetMaxCount = maxCount; |
161 | 0 | return *this; |
162 | 0 | } |
163 | | |
164 | | inline ConstructorOptions &SetInputDatasetInputFlags(int flags) |
165 | 0 | { |
166 | 0 | inputDatasetInputFlags = flags; |
167 | 0 | return *this; |
168 | 0 | } |
169 | | |
170 | | inline ConstructorOptions &SetInputDatasetHelpMsg(const std::string &s) |
171 | 0 | { |
172 | 0 | inputDatasetHelpMsg = s; |
173 | 0 | return *this; |
174 | 0 | } |
175 | | |
176 | | inline ConstructorOptions &SetInputDatasetAlias(const std::string &s) |
177 | 0 | { |
178 | 0 | inputDatasetAlias = s; |
179 | 0 | return *this; |
180 | 0 | } |
181 | | |
182 | | inline ConstructorOptions &SetInputDatasetMetaVar(const std::string &s) |
183 | 0 | { |
184 | 0 | inputDatasetMetaVar = s; |
185 | 0 | return *this; |
186 | 0 | } |
187 | | |
188 | | inline ConstructorOptions &SetOutputDatasetHelpMsg(const std::string &s) |
189 | 0 | { |
190 | 0 | outputDatasetHelpMsg = s; |
191 | 0 | return *this; |
192 | 0 | } |
193 | | |
194 | | inline ConstructorOptions &SetAutoOpenInputDatasets(bool b) |
195 | 0 | { |
196 | 0 | autoOpenInputDatasets = b; |
197 | 0 | return *this; |
198 | 0 | } |
199 | | |
200 | | inline ConstructorOptions &SetOutputDatasetRequired(bool b) |
201 | 0 | { |
202 | 0 | outputDatasetRequired = b; |
203 | 0 | return *this; |
204 | 0 | } |
205 | | |
206 | | inline ConstructorOptions & |
207 | | SetOutputFormatCreateCapability(const std::string &capability) |
208 | 0 | { |
209 | 0 | outputFormatCreateCapability = capability; |
210 | 0 | return *this; |
211 | 0 | } |
212 | | |
213 | | inline ConstructorOptions &SetAddAppendLayerArgument(bool b) |
214 | 0 | { |
215 | 0 | addAppendLayerArgument = b; |
216 | 0 | return *this; |
217 | 0 | } |
218 | | |
219 | | inline ConstructorOptions &SetAddOverwriteLayerArgument(bool b) |
220 | 0 | { |
221 | 0 | addOverwriteLayerArgument = b; |
222 | 0 | return *this; |
223 | 0 | } |
224 | | |
225 | | inline ConstructorOptions &SetAddUpdateArgument(bool b) |
226 | 0 | { |
227 | 0 | addUpdateArgument = b; |
228 | 0 | return *this; |
229 | 0 | } |
230 | | |
231 | | inline ConstructorOptions &SetAddUpsertArgument(bool b) |
232 | 0 | { |
233 | 0 | addUpsertArgument = b; |
234 | 0 | return *this; |
235 | 0 | } |
236 | | |
237 | | inline ConstructorOptions &SetNoCreateEmptyLayersArgument(bool b) |
238 | 0 | { |
239 | 0 | addNoCreateEmptyLayersArgument = b; |
240 | 0 | return *this; |
241 | 0 | } |
242 | | |
243 | | inline ConstructorOptions &SetAddSkipErrorsArgument(bool b) |
244 | 0 | { |
245 | 0 | addSkipErrorsArgument = b; |
246 | 0 | return *this; |
247 | 0 | } |
248 | | |
249 | | inline ConstructorOptions &SetAddOutputLayerNameArgument(bool b) |
250 | 0 | { |
251 | 0 | addOutputLayerNameArgument = b; |
252 | 0 | return *this; |
253 | 0 | } |
254 | | |
255 | | inline ConstructorOptions & |
256 | | SetOutputLayerNameAvailableInPipelineStep(bool b) |
257 | 0 | { |
258 | 0 | outputLayerNameAvailableInPipelineStep = b; |
259 | 0 | return *this; |
260 | 0 | } |
261 | | }; |
262 | | |
263 | | GDALPipelineStepAlgorithm(const std::string &name, |
264 | | const std::string &description, |
265 | | const std::string &helpURL, |
266 | | const ConstructorOptions &); |
267 | | |
268 | | friend class GDALPipelineAlgorithm; |
269 | | friend class GDALRasterPipelineAlgorithm; |
270 | | friend class GDALVectorPipelineAlgorithm; |
271 | | friend class GDALMdimPipelineAlgorithm; |
272 | | friend class GDALAbstractPipelineAlgorithm; |
273 | | |
274 | | virtual bool CanBeFirstStep() const |
275 | 0 | { |
276 | 0 | return false; |
277 | 0 | } |
278 | | |
279 | | virtual bool CanBeMiddleStep() const |
280 | 0 | { |
281 | 0 | return !CanBeFirstStep() && !CanBeLastStep(); |
282 | 0 | } |
283 | | |
284 | | virtual bool CanBeLastStep() const |
285 | 0 | { |
286 | 0 | return false; |
287 | 0 | } |
288 | | |
289 | | //! Whether a user parameter can cause a file to be written at a specified location |
290 | | virtual bool GeneratesFilesFromUserInput() const |
291 | 0 | { |
292 | 0 | return false; |
293 | 0 | } |
294 | | |
295 | | virtual bool IsNativelyStreamingCompatible() const |
296 | 0 | { |
297 | 0 | return true; |
298 | 0 | } |
299 | | |
300 | | virtual bool SupportsInputMultiThreading() const |
301 | 0 | { |
302 | 0 | return false; |
303 | 0 | } |
304 | | |
305 | | virtual bool CanHandleNextStep(GDALPipelineStepAlgorithm *) const |
306 | 0 | { |
307 | 0 | return false; |
308 | 0 | } |
309 | | |
310 | | virtual bool OutputDatasetAllowedBeforeRunningStep() const |
311 | 0 | { |
312 | 0 | return false; |
313 | 0 | } |
314 | | |
315 | | virtual CPLJSONObject Get_OGR_SCHEMA_OpenOption_Layer() const |
316 | 0 | { |
317 | 0 | CPLJSONObject obj; |
318 | 0 | obj.Deinit(); |
319 | 0 | return obj; |
320 | 0 | } |
321 | | |
322 | | virtual bool RunStep(GDALPipelineStepRunContext &ctxt) = 0; |
323 | | |
324 | | bool m_standaloneStep = false; |
325 | | const ConstructorOptions m_constructorOptions; |
326 | | bool m_outputVRTCompatible = true; |
327 | | std::string m_helpDocCategory{}; |
328 | | |
329 | | // Input arguments |
330 | | std::vector<GDALArgDatasetValue> m_inputDataset{}; |
331 | | std::vector<std::string> m_openOptions{}; |
332 | | std::vector<std::string> m_inputFormats{}; |
333 | | std::vector<std::string> m_inputLayerNames{}; |
334 | | |
335 | | // Output arguments |
336 | | bool m_stdout = false; |
337 | | std::string m_output{}; |
338 | | GDALArgDatasetValue m_outputDataset{}; |
339 | | std::string m_format{}; |
340 | | std::vector<std::string> m_outputOpenOptions{}; |
341 | | std::vector<std::string> m_creationOptions{}; |
342 | | bool m_overwrite = false; |
343 | | std::string m_outputLayerName{}; |
344 | | GDALInConstructionAlgorithmArg *m_outputFormatArg = nullptr; |
345 | | bool m_appendRaster = false; |
346 | | |
347 | | // Output arguments (vector specific) |
348 | | std::vector<std::string> m_layerCreationOptions{}; |
349 | | bool m_update = false; |
350 | | bool m_overwriteLayer = false; |
351 | | bool m_appendLayer = false; |
352 | | bool m_upsert = false; |
353 | | bool m_skipErrors = false; |
354 | | bool m_noCreateEmptyLayers = false; |
355 | | |
356 | | void AddRasterInputArgs(bool openForMixedRasterVector, bool hiddenForCLI); |
357 | | void AddRasterOutputArgs(bool hiddenForCLI); |
358 | | void AddRasterHiddenInputDatasetArg(); |
359 | | |
360 | | void AddVectorInputArgs(bool hiddenForCLI); |
361 | | void AddVectorHiddenInputDatasetArg(); |
362 | | void AddVectorOutputArgs(bool hiddenForCLI, |
363 | | bool shortNameOutputLayerAllowed); |
364 | | using GDALAlgorithm::AddOutputLayerNameArg; |
365 | | void AddOutputLayerNameArg(bool hiddenForCLI, |
366 | | bool shortNameOutputLayerAllowed); |
367 | | |
368 | | void AddMdimInputArgs(bool openForMixedRasterVector, bool hiddenForCLI, |
369 | | bool acceptRaster); |
370 | | void AddMdimOutputArgs(bool hiddenForCLI); |
371 | | void AddMdimHiddenInputDatasetArg(); |
372 | | |
373 | | bool CreateDatasetSingleOutputLayerIfNeeded( |
374 | | GDALPipelineStepRunContext &ctxt, const std::string &defaultLayerName, |
375 | | GDALDataset *&poDstDS, bool &bTemporaryFile, |
376 | | std::unique_ptr<GDALDataset> &poNewRetDS, std::string &outputLayerName, |
377 | | OGRLayer *&poDstLayer); |
378 | | |
379 | | private: |
380 | | bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override; |
381 | | GDALAlgorithm::ProcessGDALGOutputRet ProcessGDALGOutput() override; |
382 | | bool CheckSafeForStreamOutput() override; |
383 | | |
384 | | CPL_DISALLOW_COPY_ASSIGN(GDALPipelineStepAlgorithm) |
385 | | }; |
386 | | |
387 | | //! @endcond |
388 | | |
389 | | #endif |