libraries/edge/opensearch/solrcmrtemplateresponse.py (169 lines of code) (raw):

import datetime import pycurl from io import StringIO import json import logging import urllib.request, urllib.parse, urllib.error import os.path from edge.opensearch.templateresponse import TemplateResponse class SolrCmrTemplateResponse(TemplateResponse): def __init__(self, configuration, link, parameters): super(SolrCmrTemplateResponse, self).__init__() self._configuration = configuration self.link = link self.parameters = parameters def generate(self, solrResponse, pretty=False): self._populate(solrResponse) return super(SolrCmrTemplateResponse, self).generate(pretty) def _get_cmr_response(self, url, cmr): # Execute the curl command and load the json object. buffer = StringIO() try: c = pycurl.Curl() c.setopt(c.URL, url) c.setopt(c.WRITEDATA, buffer) c.perform() c.close() except: output = '{ "errors": "%s" }' %(c.errstr()) c.close() else: try: output = json.loads(buffer.getvalue()) except: output = '{ "errors": "json loads failed: [%s]" }' %(buffer.getvalue()) # Format the output if there are errors. response = {} if list(output.keys()).__contains__('errors'): response['entry'] = [] response['updated'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") response['id'] = url if url.find('collections') != -1: response['title'] = 'ECHO dataset metadata' elif url.find('granules') != -1: response['title'] = 'ECHO granule metadata' response['errors'] = output['errors'][0] else: response = output try: if list(response.keys()).__contains__('errors'): return(response) if not(list(response.keys()).__contains__('feed')): raise ValueError('no "feed" in the cmr response') if not(list(response['feed'].keys()).__contains__('entry')): raise ValueError('no "entry" in the cmr response') if not(list(response['feed'].keys()).__contains__('updated')): raise ValueError('no "updated" key in the cmr response') if not(list(response['feed'].keys()).__contains__('id')): raise ValueError('no "id" key in the cmr response') if not(list(response['feed'].keys()).__contains__('title')): raise ValueError('no "id" key in the cmr response') # Create lists if they do not exists. if not(list(cmr.keys()).__contains__('cmr_search_updated')): cmr['cmr_search_updated'] = [] if not(list(cmr.keys()).__contains__('cmr_search_url')): cmr['cmr_search_url'] = [] if not(list(cmr.keys()).__contains__('cmr_search_title')): cmr['cmr_search_title'] = [] cmr['cmr_search_updated'].append(response['feed']['updated']) cmr['cmr_search_url'].append(response['feed']['id']) cmr['cmr_search_title'].append(response['feed']['title']) # Create list objects for the "entry" key. if response['feed']['entry'] != []: entry = response['feed']['entry'][0] for key in entry: keyname = 'cmr_%s' %(key) if not(list(cmr.keys()).__contains__(keyname)): cmr[keyname] = [] cmr[keyname].append(entry[key]) except ValueError as e: msg = 'Error! parse error: %s.' %e print('%s\n' %msg) return(cmr) def _populate(self, solrResponse): self.variables['link'] = self.link start = 0 rows = 0 numFound = 0 if solrResponse is not None: solrJson = json.loads(solrResponse) logging.debug('Total doc count: '+str(solrJson['response']['numFound'])) logging.debug('Total item count: '+ str(len(solrJson['response']['docs']))) #---------------------------------------------------------------------------------------------- # CMR: Processing #---------------------------------------------------------------------------------------------- cmr_total_time = datetime.timedelta(0) cmr_total_count = 0 for i in range(len(solrJson['response']['docs'])): doc = solrJson['response']['docs'][i] logging.debug('doc[id]: '+str(doc['id'])) #------------------------------------------------------------------------------------------ # CMR: Initialize #------------------------------------------------------------------------------------------ cmr = {} #------------------------------------------------------------------------------------------ # CMR: PRODUCT_TYPE #------------------------------------------------------------------------------------------ if list(solrJson['response']['docs'][i].keys()).__contains__('product_type_dataset_short_name_list'): for j in range(len(doc['product_type_dataset_short_name_list'])): cmr_test = 0 if cmr_test == 1: cmr_search_url = 'https://cmr.earthdata.nasa.gov/search/collections.json?keyword=NSIDC' else: cmr_search_url = 'https://cmr.earthdata.nasa.gov/search/collections.json?keyword=' + \ doc['product_type_dataset_short_name_list'][j] logging.debug('cmr search url: ' +cmr_search_url) time1 = datetime.datetime.now() cmr = self._get_cmr_response(cmr_search_url, cmr) time2 = datetime.datetime.now() time3 = time2 - time1 logging.debug('cmr search time: ' + time3.__str__() + ' 1 product_type') cmr_total_time = cmr_total_time + time3 cmr_total_count = cmr_total_count + 1 #------------------------------------------------------------------------------------------ # CMR: PRODUCT (Only search when the query contains 'id' - ie individual cmr search) #------------------------------------------------------------------------------------------ elif list(solrJson['response']['docs'][i].keys()).__contains__('product_granule_remote_granule_ur_list') and \ list(self.parameters.keys()).__contains__('id'): for j in range(len(doc['product_granule_remote_granule_ur_list'])): cmr_test = 0 if cmr_test == 1: cmr_search_url = 'https://cmr.earthdata.nasa.gov/search/granules.json?granule_ur[]=' + \ '20070106-NAR18_SST-EUR-L2P-sst1nar_noaa18_20070106_asc-v01.nc' else: cmr_search_url = 'https://cmr.earthdata.nasa.gov/search/granules.json?granule_ur[]=' + \ doc['product_granule_remote_granule_ur_list'][j] logging.debug('cmr search url: ' +cmr_search_url) time1 = datetime.datetime.now() cmr = self._get_cmr_response(cmr_search_url, cmr) time2 = datetime.datetime.now() time3 = time2 - time1 logging.debug('cmr search time: ' + time3.__str__() + ' 1 product') cmr_total_time = cmr_total_time + time3 cmr_total_count = cmr_total_count + 1 #------------------------------------------------------------------------------------------ # CMR: Docs not containing CMR search related criteria #------------------------------------------------------------------------------------------ else: continue #------------------------------------------------------------------------------------------ # CMR: Post-processing #------------------------------------------------------------------------------------------ if cmr != {}: doc.update(cmr) #print json.dumps(cmr, indent=4) else: logging.debug('***>>> cmr was not set') #------------------------------------------------------------------------------------------ # CMR: End #------------------------------------------------------------------------------------------ self.variables['docs'] = solrJson['response']['docs'] self.variables['numFound'] = solrJson['response']['numFound'] self.variables['itemsPerPage'] = solrJson['responseHeader']['params']['rows'] self.variables['startIndex'] = solrJson['response']['start'] self.variables['updated'] = datetime.datetime.utcnow().isoformat() + 'Z' start = int(solrJson['response']['start']) rows = int(solrJson['responseHeader']['params']['rows']) numFound = int(solrJson['response']['numFound']) logging.debug('Num docs found: ' + str(self.variables['numFound'])) logging.debug('Items per page: ' + str(self.variables['itemsPerPage'])) # Show CMR statistics. cmr_type = '' if os.path.basename(self.variables['link']) == 'product_type': cmr_type = 'dataset' elif os.path.basename(self.variables['link']) == 'product': cmr_type = 'granule' if (cmr_type == 'dataset' or cmr_type == 'granule') and cmr_total_count != 0: cmr_average_time = cmr_total_time/cmr_total_count cmr_stats_msg = 'CMR search results: %s total per/%d %s(s) %s average per/%s' \ %(cmr_total_time.__str__(), cmr_total_count, cmr_type, cmr_average_time.__str__(), cmr_type) logging.debug(cmr_stats_msg) if 'facet_counts' in solrJson: self.variables['facets'] = solrJson['facet_counts'] self.parameters['startIndex'] = start self.variables['myself'] = self.link + '?' + urllib.parse.urlencode(self.parameters, True) if rows != 0: self.parameters['startIndex'] = numFound - (numFound % rows) self.variables['last'] = self.link + '?' + urllib.parse.urlencode(self.parameters, True) self.parameters['startIndex'] = 0 self.variables['first'] = self.link + '?' + urllib.parse.urlencode(self.parameters, True) if start > 0: if (start - rows > 0): self.parameters['startIndex'] = start - rows self.variables['prev'] = self.link + '?' + urllib.parse.urlencode(self.parameters, True) if start + rows < numFound: self.parameters['startIndex'] = start + rows self.variables['next'] = self.link + '?' + urllib.parse.urlencode(self.parameters, True)