@@ -163,11 +163,15 @@ def _check_input_parameters_valid(self, product_type: str, params: Any):
163163 Check if all required parameters are given and if the values are valid
164164 raises a ValidationError if this is not the case
165165 """
166- constraints_values = self ._fetch_constraints (product_type )["constraints" ]
166+ constraints_data = self ._fetch_constraints (product_type )
167+ constraints_values = constraints_data ["constraints" ]
167168 # get available values - will raise error if wrong parameters or wrong parameter values in request
169+ grouped_by = params .pop ("grouped_by" , None )
168170 available_values = _get_available_values_from_constraints (
169171 constraints_values , params , product_type
170172 )
173+ if grouped_by and grouped_by not in params :
174+ params [grouped_by ] = available_values [grouped_by ]
171175 missing_params = set (available_values .keys ()) - set (params .keys ())
172176 if missing_params :
173177 raise ValidationError (
@@ -182,6 +186,50 @@ def _check_input_parameters_valid(self, product_type: str, params: Any):
182186 set (available_values ["month" ])
183187 )
184188
189+ def _get_start_and_end_from_properties (
190+ self , properties : dict [str , Any ]
191+ ) -> dict [str , str ]:
192+ """get the start and end time from year/month in the properties or missionStart/EndDate"""
193+ if "month" in properties :
194+ start_date = datetime .datetime (
195+ year = int (properties ["year" ]),
196+ month = int (properties ["month" ]),
197+ day = 1 ,
198+ hour = 0 ,
199+ minute = 0 ,
200+ second = 0 ,
201+ )
202+ end_day = monthrange (int (properties ["year" ]), int (properties ["month" ]))[1 ]
203+ end_date = datetime .datetime (
204+ year = int (properties ["year" ]),
205+ month = int (properties ["month" ]),
206+ day = end_day ,
207+ hour = 23 ,
208+ minute = 59 ,
209+ second = 59 ,
210+ )
211+ elif "year" in properties :
212+ start_date = datetime .datetime (
213+ year = int (properties ["year" ]), month = 1 , day = 1 , hour = 0 , minute = 0 , second = 0
214+ )
215+ end_date = datetime .datetime (
216+ year = int (properties ["year" ]),
217+ month = 12 ,
218+ day = 31 ,
219+ hour = 23 ,
220+ minute = 59 ,
221+ second = 59 ,
222+ )
223+ else :
224+ start_date = self .get_product_type_cfg_value ("missionStartDate" )
225+ end_date = self .get_product_type_cfg_value ("missionEndDate" )
226+ return {"start_date" : start_date , "end_date" : end_date }
227+
228+ result = {}
229+ result ["start_date" ] = start_date .strftime ("%Y-%m-%dT%H:%M:%SZ" )
230+ result ["end_date" ] = end_date .strftime ("%Y-%m-%dT%H:%M:%SZ" )
231+ return result
232+
185233 def _create_products_from_tiles (
186234 self ,
187235 tiles : dict [str , list [dict [str , Any ]]],
@@ -287,77 +335,63 @@ def _create_products_without_tiles(
287335 default_geometry = getattr (self .config , "metadata_mapping" )["defaultGeometry" ]
288336 properties = {}
289337 properties ["geometry" ] = default_geometry [1 ]
290- download_link = (
291- self .config .products .get (product_type , {})
292- .get ("metadata_mapping" , {})
293- .get ("downloadLink" , None )
338+ product_type_config = self .config .products .get (product_type , {})
339+ download_link = product_type_config .get ("metadata_mapping" , {}).get (
340+ "downloadLink" , None
294341 )
295342 if not download_link :
296343 raise MisconfiguredError (
297344 f"Download link configuration missing for product type { product_type } "
298345 )
299- properties [ "downloadLink" ] = download_link
346+
300347 # product type with assets mapping
301348 assets_mapping = filters .pop ("assets_mapping" , None )
302349 products = []
303350 start_index = prep .items_per_page * (prep .page - 1 )
304351 end_index = start_index + prep .items_per_page - 1
305- if assets_mapping :
352+ grouped_by = filters .pop ("grouped_by" , None )
353+ if grouped_by : # dataset with several files differentiated by one parameter
306354 format_params = {k : str (v ) for k , v in filters .items () if v }
307355 format_params .pop ("metadata_mapping" , None )
308- months = filters . get ( "month" , "12" )
309- num_products = len ( months )
310- if isinstance ( months , str ) or isinstance ( months , int ):
311- months = [ months ]
312- for i , month in enumerate (months ):
356+ grouped_by_values = filters [ grouped_by ]
357+ if isinstance ( grouped_by_values , str ) or isinstance ( grouped_by_values , int ):
358+ grouped_by_values = [ grouped_by_values ]
359+ num_products = len ( grouped_by_values )
360+ for i , value in enumerate (grouped_by_values ):
313361 if i < start_index :
314362 continue
315- filters ["month" ] = format_params ["month" ] = str (month )
363+ filters [grouped_by ] = format_params [grouped_by ] = str (value )
316364 product_id = product_type + "__" + "_" .join (format_params .values ())
317365 properties ["id" ] = properties ["title" ] = product_id
318- end_day = monthrange (int (filters ["year" ]), int (month ))[1 ]
319- start_time = datetime .datetime (
320- year = int (filters ["year" ]),
321- month = int (month ),
322- day = 1 ,
323- hour = 0 ,
324- minute = 0 ,
325- second = 0 ,
326- )
327- end_time = datetime .datetime (
328- year = int (filters ["year" ]),
329- month = int (month ),
330- day = end_day ,
331- hour = 23 ,
332- minute = 59 ,
333- second = 59 ,
334- )
335- properties ["startTimeFromAscendingNode" ] = start_time .strftime (
336- "%Y-%m-%dT%H:%M:%SZ"
337- )
338- properties ["completionTimeFromAscendingNode" ] = end_time .strftime (
339- "%Y-%m-%dT%H:%M:%SZ"
340- )
366+ properties ["downloadLink" ] = download_link .format (** format_params )
367+ datetimes = self ._get_start_and_end_from_properties (format_params )
368+ properties ["startTimeFromAscendingNode" ] = datetimes ["start_date" ]
369+ properties ["completionTimeFromAscendingNode" ] = datetimes ["end_date" ]
341370 product = EOProduct (
342371 provider = "cop_ghsl" , properties = properties , productType = product_type
343372 )
344- assets = AssetsDict (product = product )
345- for key , mapping in assets_mapping .items ():
346- download_link = mapping ["href" ].format (** filters )
347- assets [key ] = Asset (
348- product = product ,
349- key = key ,
350- href = download_link ,
351- title = mapping ["title" ],
352- type = mapping ["type" ],
353- )
354- product .assets = assets
373+ if assets_mapping : # item with several assets
374+ assets = AssetsDict (product = product )
375+ for key , mapping in assets_mapping .items ():
376+ download_link = mapping ["href" ].format (** filters )
377+ assets [key ] = Asset (
378+ product = product ,
379+ key = key ,
380+ href = download_link ,
381+ title = mapping ["title" ],
382+ type = mapping ["type" ],
383+ )
384+ product .assets = assets
355385 products .append (product )
356386 if i == end_index :
357387 break
358388 else : # product type with only one file to download
359389 product_id = f"{ product_type } _ALL"
360390 properties ["id" ] = properties ["title" ] = product_id
391+ datetimes = self ._get_start_and_end_from_properties (properties )
392+ properties ["startTimeFromAscendingNode" ] = datetimes ["start_date" ]
393+ properties ["completionTimeFromAscendingNode" ] = datetimes ["end_date" ]
394+ properties ["downloadLink" ] = download_link
361395 product = EOProduct (
362396 provider = "cop_ghsl" , properties = properties , productType = product_type
363397 )
@@ -423,10 +457,13 @@ def _get_tiles_for_filters(
423457 filter_params .pop ("assets_mapping" , None )
424458
425459 self ._check_input_parameters_valid (product_type , filter_params )
426- if "year" in filter_params :
427- params [ "year" ] = filter_params [ "year" ]
460+ # update parameters based on changes during validation
461+ params . update ( filter_params )
428462
429463 # fetch available tiles based on filters
464+ if "year" not in filter_params :
465+ logger .warning (f"no tiles available for { product_type } " )
466+ return None
430467 if isinstance (filter_params ["year" ], int ) or isinstance (
431468 filter_params ["year" ], str
432469 ):
0 commit comments