def checkOnlineResourceDesc(self, val, length): #print("Input of checkOnlineResourceDesc() is ...") if length == 1: if val == None: return errors.not_provided() else: return "OK - quality check" else: flag = False flag1 = False flag2 = False descs = [] for i in range(0, length): try: if val[i]["Description"] != None: flag = True if val[i]["Description"] not in descs: descs.append(val[i]["Description"]) else: flag1 = True else: flag2 = True except KeyError: flag2 = True if (flag and flag2): return "Recommend providing a description for each Online Access URL." elif (flag1): return "Descriptions should be unique to each URL. Several of the descriptions are repeated in this record. Recommend changing descriptions to more accurately and uniquely describe the URL." elif (flag and not flag1 and not flag2): return "OK - quality check" else: return errors.not_provided()
def checkPlatformShortName(self, val, length): #print("Input of checkPlatformShortName() is ...") PlatformKeys = list() PlatformLongNames = list() response = requests.get(PlatformURL).text.split('\n') data = csv.reader(response) next(data) # Skip the first two line information next(data) for item in data: PlatformKeys += item[2:3] PlatformLongNames += item[3:4] PlatformKeys = list(set(PlatformKeys)) PlatformLongNames = list(set(PlatformLongNames)) if length == 1: if val == None: return errors.not_provided() if val not in PlatformKeys: if val in PlatformLongNames: return val + ": incorrect keyword order" else: return "The keyword does not conform to GCMD" else: for i in range(0, length): if val[i]['ShortName'] == None: return errors.not_provided() if val[i]['ShortName'] not in PlatformKeys: if val[i]['ShortName'] in PlatformLongNames: return val[i]['ShortName'] + ": incorrect keyword order" else: return "The keyword does not conform to GCMD" return "OK - quality check"
def checkEquatorCrossingTime(self, val, length): #print("Input of checkEquatorCrossingTime() is ...") if length == 1: return self.__checkTimeStr( val, errors.not_provided(), errors.okay(), errors_date_format_error(val), errors_date_format_day_error(val), errors_date_format_month_error(val), errors_date_format_inserttime_future_error(val)) ''' try: if val == None: return errors.not_provided() if not val.endswith("Z"): return "DateTime error" val = val.replace("Z", "") t_record = datetime.strptime(val, '%Y-%m-%dT%H:%M:%S') if t_record.microsecond / 1000 > 999: return "DateTime error" t_now = datetime.now() if t_record.year > t_now.year: return "DateTime error" return "OK - quality check" except ValueError: return "DateTime error" ''' else: for i in range(0, length): return self.__checkTimeStr( val['EquatorCrossingDateTime'], errors.not_provided(), errors.okay(), errors_date_format_error(val), errors_date_format_day_error(val), errors_date_format_month_error(val), errors_date_format_inserttime_future_error(val)) '''
def checkTemporalSingleTime(self, val): #print("Input of checkTemporalSingleTime() is " + val) return self.__checkTimeStr( val, errors.not_provided(), errors.okay(), errors_date_format_error(val), errors_date_format_day_error(val), errors_date_format_month_error(val), errors_date_format_inserttime_future_error(val)) '''
def checkProductionDateTime(self, prodTime, insertTime): #print("Input of checkProductionDateTime() is " + prodTime + ', ' + insertTime) return self.__checkTimeStr( val, errors.not_provided(), errors.okay(), errors_date_format_error(val), errors_date_format_day_error(val), errors_date_format_month_error(val), errors_date_format_inserttime_future_error(val)) '''
def checkDayNightFlag(set, val): #print("Input of checkDayNightFlag() is " + val) DNFlags = ('DAY', 'NIGHT', 'BOTH', 'UNSPECIFIED') if val == None: return errors.not_provided() elif val.upper() not in DNFlags: return "Invalid value for DayNightFlag. Valid values include: DAY; NIGHT; BOTH; UNSPECIFIED" else: return errors.okay()
def checkOnlineResourceURL(self, val, length): #print("Input of checkOnlineResourceURL() is ...") #print("Input of checkOnlineAccessURL() is ...") check = [] broken = [] okay = [] ftp = [] http = [] if length == 1: if val == None: return errors.not_provided() error = self.checkURL(val) + '\n' + val[i]['URL'] return error else: error = '' for i in range(0, length): if val[i]['URL'] == None: return errors.not_provided() else: if self.checkURL(val[i]['URL']) == errors.check_link(): check.append(val[i]['URL']) elif self.checkURL(val[i]['URL']) == errors.broken_url(): broken.append(val[i]['URL']) elif self.checkURL(val[i]['URL']) == errors.http(): http.append(val[i]['URL']) elif self.checkURL(val[i]['URL']) == errors.ftp(): ftp.append(val[i]['URL']) elif self.checkURL(val[i]['URL']) == errors.okay(): okay.append(val[i]['URL']) if len(check) > 0: error += errors.check_link() + '\n' + '\n'.join(check) if len(broken) > 0: error += errors.broken_url() + '\n' + '\n'.join(check) if len(http) > 0: error += errors.http() + '\n' + '\n'.join(check) if len(ftp) > 0: error += errors.ftp() + '\n' + '\n'.join(check) if len(okay) > 0 and (len(check) == 0 or len(broken) == 0 or len(http) == 0 or len(ftp) == 0): error += errors.okay() return error
def checkOnlineResourceType(self, val, length): #print("Input of checkOnlineResourceType() is ...") ResourcesTypes = list() response = requests.get(ResourcesTypeURL).text.split('\n') data = csv.reader(response) next(data) # Skip the first two row information next(data) for item in data: ResourcesTypes += item[0:1] ResourcesTypes = list(set(ResourcesTypes)) UmmEnumTypes = self.enums['RelatedUrlTypeEnum'] UmmEnumTypes.extend(self.enums['RelatedURLSubTypeEnum']) listA = [ "THREDDS CATALOG", "THREDDS DATA", "THREDDS DIRECTORY", "GET WEB MAP FOR TIME SERIES", "GET RELATED VISUALIZATION", "GIOVANNI", "WORLDVIEW", "GET MAP SERVICE" ] listB = [ "GET WEB MAP SERVICE (WMS)", "GET WEB COVERAGE SERVICE (WCS)", "OPENDAP DATA (DODS)" ] Results = [[], [], [], [], []] if length == 1: val = [val] for v in val: try: t = v['Type'] if t in listA: Results[1].append(t) elif t in listB: Results[2].append(t) elif t in UmmEnumTypes: Results[3].append(t) else: Results[4].append(t) except Exception as e: return "Each Online Resource URL must be accompanied by a URL Type. Valid values can be found in the UMM-Common schema. A type may be selected from either the URL Type enum or the URL Subtype enum. https://git.earthdata.nasa.gov/projects/EMFD/repos/unified-metadata-model/browse/v1.10/umm-cmn-json-schema.json" if Results[4]: return "Invalid URL Types: " + "; ".join( Results[4] ) + "\nA valid type may be selected from either the URL Type enum or the URL Subtype enum. https://git.earthdata.nasa.gov/projects/EMFD/repos/unified-metadata-model/browse/v1.10/umm-cmn-json-schema.json" # result = "; ".join(['; '.join(r) for r in Results[1:3] if r]) elif Results[2]: return "OK - two points for data accessability score for providing an advanced service for visualization, subsetting or aggregation which also meets common framework requirements for standard API based data access." elif Results[1]: return "OK - one point for data accessability score for providing an advanced service for visualization, subsetting or aggregation" elif Results[0]: return errors.okay() else: return errors.not_provided()
def checkCampaignShortName(self, val, campaignNum): #print("Input of checkCampaignShortName() is ...") CampaignKeys = list() CampaignLongNames = list() response = requests.get(ProjectURL).text.split('\n') data = csv.reader(response) next(data) # Skip the first two line information next(data) for item in data: if len(item) != 0: CampaignKeys += item[1:2] CampaignLongNames += item[2:3] CampaignKeys = list(set(CampaignKeys)) CampaignLongNames = list(set(CampaignLongNames)) if campaignNum == 1: if val == None: return errors.not_provided() elif val not in CampaignKeys: if val in CampaignLongNames: return val + ": incorrect keyword order" else: return "The keyword does not conform to GCMD." else: return errors.okay() else: for i in range(campaignNum): if val[i]['Campaign']['ShortName'] == None: return errors.not_provided() elif val[i]['Campaign']['ShortName'] not in CampaignKeys: if val[i]['Campaign']['ShortName'] in CampaignLongNames: return val[i]['Campaign'][ 'ShortName'] + ": incorrect keyword order" else: return "The keyword does not conform to GCMD." else: return errors.okay()
def checkInsertTime(self, val): #print("Input of checkInsertTime() is " + val) try: if val == None: return errors.not_provided() if not val.endswith("Z"): return "InsertTime error." val = val.replace("Z", "") t_record = datetime.strptime(val, '%Y-%m-%dT%H:%M:%S') if t_record.microsecond / 1000 > 999: return "InsertTime error." t_now = datetime.now() if t_record.year > t_now.year: return "InsertTime error." return errors.okay() except ValueError: return "InsertTime error."
def checkDeleteTime(self, deleteTime, prodTime): #print("Input of checkDeleteTime() is " + deleteTime + ', ' + prodTime) try: if deleteTime == None: return errors.not_provided() elif not deleteTime.endswith("Z"): return "Delete time error" deleteTime = deleteTime.replace("Z", "") t_record = datetime.strptime(deleteTime, '%Y-%m-%dT%H:%M:%S') prodTime = prodTime.replace("Z", "") p_record = datetime.strptime(prodTime, '%Y-%m-%dT%H:%M:%S') if t_record.microsecond / 1000 > 999: return "Delete time error" if p_record > t_record: return "Delete time error" return "OK - quality check" except ValueError: return "Delete time error"
def checkLastUpdate(self, updateTime, prodTime): #print("Input of checkLastUpdate() is " + updateTime + ', ' + prodTime) try: if updateTime == None: return errors.not_provided() elif not updateTime.endswith("Z"): return "LastUpdate time error." updateTime = updateTime.replace("Z", "") t_record = datetime.strptime(updateTime, '%Y-%m-%dT%H:%M:%S') prodTime = prodTime.replace("Z", "") p_record = datetime.strptime(prodTime, '%Y-%m-%dT%H:%M:%S') if t_record.microsecond / 1000 > 999: return "LastUpdate time error." t_now = datetime.now() if t_record.year > t_now.year or t_record < p_record: return "LastUpdate time error." return errors.okay() except ValueError: return "LastUpdate time error."
def checkVisible(self, val): print("Input of checkVisible() is " + val) if val == None: return errors.not_provided() else: return "Note: The Visible field is being deprecated in UMM."
def checkInstrShortName(self, val, platformNum, instruments): #print("Input of checkInstrShortName() is ...") processInstrCount = 0 InstrumentKeys = instruments[4] SensorResult = '' if platformNum == 1: val = [val] ''' try: # ------- try: val['Instruments']['Instrument']['Sensors']['Sensor'] if val['Instruments']['Instrument']['Sensors']['Sensor']['ShortName'] == \ val['Instruments']['Instrument']['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." except TypeError: sensor_len = len(val['Instruments']['Instrument']['Sensors']) for s in range(sensor_len): try: if val['Instruments']['Instrument']['Sensors'][s]['Sensor']['ShortName'] == \ val['Instruments']['Instrument']['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." break except KeyError: continue except KeyError: SensorResult = 'np' # if len(SensorResult) == 0: # SensorResult = 'Recommend removing sensors from the metadata; since this field will be deprecated in the future.' # ------- if val['Instruments']['Instrument']['ShortName'] == None: return errors.not_provided(), SensorResult if not any(s.lower() == val['Instruments']['Instrument']['ShortName'].lower() for s in InstrumentKeys): return "The keyword does not conform to GCMD.", SensorResult processInstrCount += 1 except TypeError: instrNum = len(val['Instruments']['Instrument']) for instr in range(0, instrNum): # ------- try: val['Instruments']['Instrument'][instr]['Sensors']['Sensor'] if val['Instruments']['Instrument'][instr]['Sensors']['Sensor']['ShortName'] == \ val['Instruments']['Instrument'][instr]['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." except TypeError: sensor_len = len(val['Instruments']['Instrument'][instr]['Sensors']) for s in range(sensor_len): try: if val['Instruments']['Instrument'][instr]['Sensors'][s]['Sensor']['ShortName'] == \ val['Instruments']['Instrument'][instr]['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." break except KeyError: continue except KeyError: SensorResult = errors.not_provided() # if len(SensorResult) == 0: # SensorResult = 'Recommend removing sensors from the metadata; since this field will be deprecated in the future.' # ------- if val['Instruments']['Instrument'][instr]['ShortName'] == None: return errors.not_provided(), SensorResult if not any(s.lower() == val['Instruments']['Instrument'][instr]['ShortName'].lower() for s in InstrumentKeys): return "The keyword does not conform to GCMD.", SensorResult processInstrCount += 1 except KeyError: print("Access Key Error!") ''' #else: for i in range(0, platformNum): try: # ------- try: val[i]['Instruments']['Instrument']['Sensors']['Sensor'] if val[i]['Instruments']['Instrument']['Sensors']['Sensor']['ShortName'] == \ val[i]['Instruments']['Instrument']['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." except TypeError: sensor_len = len( val[i]['Instruments']['Instrument']['Sensors']) for s in range(sensor_len): try: if val[i]['Instruments']['Instrument']['Sensors'][s]['Sensor']['ShortName'] == \ val[i]['Instruments']['Instrument']['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." break except KeyError: SensorResult = errors.not_provided() continue except KeyError: SensorResult = errors.not_provided() # if len(SensorResult) == 0: # SensorResult = 'Recommend removing sensors from the metadata; since this field will be deprecated in the future.' # ------- if val[i]['Instruments']['Instrument']['ShortName'] == None: return errors.not_provided(), SensorResult if not any(s.lower() == val[i]['Instruments']['Instrument'] ['ShortName'].lower() for s in InstrumentKeys): return "The keyword does not conform to GCMD.", SensorResult processInstrCount += 1 except TypeError: instrNum = len(val[i]['Instruments']) for instr in range(0, instrNum): # ------- try: val[i]['Instruments']['Instrument'][instr]['Sensors'][ 'Sensor'] if val[i]['Instruments']['Instrument'][instr]['Sensors']['Sensor']['ShortName'] == \ val[i]['Instruments']['Instrument'][instr]['ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." except TypeError as e: try: sensor_len = len(val[i]['Instruments'] ['Instrument'][instr]['Sensors']) for s in range(sensor_len): try: if val[i]['Instruments']['Instrument'][ instr]['Sensors'][s]['Sensor'][ 'ShortName'] == val[i][ 'Instruments'][ 'Instrument'][instr][ 'ShortName']: SensorResult = "Same as Instrument/ShortName. Consider removing since this is redundant information." break except KeyError: continue except TypeError: return "Provide at least one relevant instrument for this dataset. This is a required field.", errors.not_provided( ) except KeyError: SensorResult = errors.not_provided() # if len(SensorResult) == 0: # SensorResult = 'Recommend removing sensors from the metadata; since this field will be deprecated in the future.' # ------- if val[i]['Instruments']['Instrument'][instr][ 'ShortName'] == None: return errors.not_provided(), SensorResult if not any(s.lower() == val[i]['Instruments']['Instrument'] [instr]['ShortName'].lower() for s in InstrumentKeys): return "The keyword does not conform to GCMD.", SensorResult processInstrCount += 1 except KeyError: continue if processInstrCount != 0: return "OK- quality check", SensorResult else: return errors.not_provided(), SensorResult