Changeset 4347 for exist


Ignore:
Timestamp:
20/10/08 09:07:15 (11 years ago)
Author:
cbyrom
Message:

Add validate() method to atom model to allow basic checks on atom data
integrity + add custom exception to allow packing of multiple error messages
into one exception + remove atom logos field - all logos data now stored
solely in the related links field to simplify things.

Location:
exist/trunk/python/ndgUtils
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • exist/trunk/python/ndgUtils/models/Atom.py

    r4314 r4347  
    3131 
    3232 
     33class ValidationError(Exception): 
     34    """ 
     35    Exception handling for validation. 
     36    """ 
     37    def __init__(self, errorDict): 
     38        msg = "Data validation error" 
     39        logging.error(msg) 
     40        Exception.__init__(self, msg) 
     41        for val in errorDict.itervalues(): 
     42            logging.error(val) 
     43        self._errorDict = errorDict 
     44             
     45    def unpack_errors(self): 
     46        return self._errorDict 
     47 
     48 
    3349class Person(object): 
    3450    ''' 
     
    215231    DELIMITER = "---" 
    216232    REMOVE_LABEL = "remove" 
    217  
     233     
     234    # format to use for t1-t2 date range 
     235    YEAR_FORMAT = '%Y-%m-%d' 
    218236 
    219237    def __init__(self, atomType = None, vocabTermData = None, ndgObject = None, \ 
     
    250268        # for this purpose 
    251269        self.contentFile = None      
    252         self.logos = [] 
    253270        self.title = None 
    254271        self.datasetID = None        # NB, the dataset id ends up in the atomName - <path><datasetID>.atom 
     
    503520 
    504521 
    505     def addLogos(self, logoVals): 
    506         ''' 
    507         Add related logos in string format - converting to Link objects 
    508         @param linkVals: string of format, 'uri | title | vocabServerURL' 
    509         ''' 
    510         self.relatedLinks.append(self.objectify(logoVals, 'logo')) 
    511  
    512  
    513522    def addParameters(self, params): 
    514523        ''' 
     
    544553            molesDoc = re.sub('ATOM','NDG-B1', self.atomBrowseURL) 
    545554            molesLink.attrib["href"] = molesDoc 
    546             molesLink.attrib["rel"] = "related" 
     555            molesLink.attrib["rel"] = 'related' 
    547556         
    548557        for relatedLink in self.relatedLinks: 
    549558            if relatedLink.hasValue(): 
    550559                root.append(relatedLink.toXML()) 
    551          
    552         for logo in self.logos: 
    553             if logo.hasValue(): 
    554                 root.append(logo.toXML()) 
    555560     
    556561    def toXML(self): 
     
    597602                     
    598603        summary = ET.SubElement(root, "summary") 
    599         summary.text = escapeSpecialCharacters(self.Summary) 
     604        summary.text = self.Summary 
    600605                     
    601606        # add link to content, if required - NB, can only have one content element in atom 
     
    606611            content.attrib["src"] = self.contentFile 
    607612        else: 
    608             content.text = escapeSpecialCharacters(self.Content) 
     613            content.text = self.Content 
     614            content.attrib["type"] = "xhtml" 
    609615         
    610616        # if there's a published date already defined, assume we're doing an update now 
     
    649655        self.summary = [] 
    650656        for summary_line in summary.split('\n'): 
    651             self.summary.append(summary_line) 
     657            self.summary.append(escapeSpecialCharacters(summary_line)) 
    652658             
    653659    Summary = property(fset=__setSummary, fget=__getSummary, doc="Atom summary") 
     
    670676        self.content = [] 
    671677        for content_line in content.split('\n'): 
    672             self.content.append(content_line) 
     678            self.content.append(escapeSpecialCharacters(content_line)) 
    673679             
    674680    Content = property(fset=__setContent, fget=__getContent, doc="Atom content") 
     
    857863            if not linkData.has_key(link.rel): 
    858864                linkData[link.rel] = [] 
    859                  
    860             if link.title == VTD.TERM_DATA[VTD.LOGO_TERM].title: 
    861                 self.logos.append(link) 
    862             else: 
    863                 linkData[link.rel].append(link) 
     865             
     866            linkData[link.rel].append(link) 
    864867 
    865868        # there should be one self referencing link - which will provide info on the atom itself 
     
    958961            return objectVals 
    959962         
    960         if attributeName == "relatedLinks" or attributeName == "logo": 
     963        if attributeName == "relatedLinks": 
    961964            obj = Link() 
    962965        elif attributeName == "atomAuthors" or attributeName == "authors": 
     
    10191022        ''' 
    10201023        logging.info("Validating the atom data model") 
    1021          
     1024        errors = {} 
     1025        if not self.title: 
     1026            errors['title'] = "Title attribute cannot be empty" 
     1027             
     1028        if self.minX or self.maxX or self.minY or self.maxY: 
     1029            missingVals = False 
     1030            incorrectFormat = False  
     1031            for val in [self.minX, self.maxX, self.minY, self.maxY]: 
     1032                if val == '': 
     1033                    missingVals = True 
     1034                else: 
     1035                    try: 
     1036                        float(val) 
     1037                    except: 
     1038                        incorrectFormat = True 
     1039             
     1040            if missingVals or incorrectFormat: 
     1041                errors['spatialcoverage'] = "" 
     1042            if missingVals: 
     1043                errors['spatialcoverage'] += "Incomplete spatial coverage data.\n" 
     1044            if incorrectFormat: 
     1045                errors['spatialcoverage'] += "Spatial coverage data not in numerical format." 
     1046 
     1047        if self.t1 or self.t2: 
     1048            timeErrors = '' 
     1049            d1 = None 
     1050            d2 = None 
     1051            if self.t1: 
     1052                try: 
     1053                    d1 = datetime.datetime.strptime(self.t1, self.YEAR_FORMAT) 
     1054                except: 
     1055                    timeErrors += "Incorrect start date format - '%s' - c.f. '2008-04-12. \n'" %self.t1 
     1056            if self.t2: 
     1057                try: 
     1058                    d2 = datetime.datetime.strptime(self.t2, self.YEAR_FORMAT) 
     1059                except: 
     1060                    timeErrors += "Incorrect end date format - '%s' - c.f. '2008-04-12. \n'" %self.t2 
     1061 
     1062            if d1 and d2: 
     1063                if d1 > d2 or d2 < d1: 
     1064                    timeErrors += "Inconsistent date range - '%s' is not before '%s'" \ 
     1065                        %(d1.strftime(self.YEAR_FORMAT), d2.strftime(self.YEAR_FORMAT)) 
     1066 
     1067            if timeErrors: 
     1068                errors['temporalrange'] = timeErrors 
     1069 
     1070             
     1071        # do a quick recursion over all the attributes to look for ascii characters 
     1072        for key, val in self.__dict__.items(): 
     1073            if val: 
     1074                if type(val) == str: 
     1075                    try: 
     1076                        # NB, the latin coding accepts unicode up to 255 
     1077                        correctedString = val.decode('latin-1') 
     1078                    except: 
     1079                        if not errors.has_key(key): 
     1080                            errors[key] = '' 
     1081                        errors[key] += "Illegal unicode found in string: '%s'.\n" %val 
     1082                 
     1083        if errors: 
     1084            logging.warning("Errors found in atom data: %s" %errors) 
     1085            raise ValidationError(errors) 
    10221086        logging.info("Atom model validated successfully") 
     1087         
     1088         
     1089    def getLogos(self): 
     1090        ''' 
     1091        Return related links that are logos 
     1092        @return: array of Links containing the logos for the atom 
     1093        ''' 
     1094        logos = [] 
     1095        for link in self.relatedLinks: 
     1096            if link.rel.lower().endswith(VTD.LOGO_TERM.lower()): 
     1097                logos.append(link) 
     1098                 
     1099        return logos 
     1100     
     1101     
     1102    def isGranule(self): 
     1103        if self.atomTypeID == VTD.GRANULE_TERM: 
     1104            return True 
     1105        return False 
     1106     
     1107     
     1108    def isDE(self): 
     1109        if self.atomTypeID == VTD.DE_TERM: 
     1110            return True 
     1111        return False 
     1112     
     1113    def isDeployment(self): 
     1114        if self.subtypeID and self.subtypeID == VTD.DEPLOYMENT_TERM: 
     1115            return True 
     1116        return False 
     1117 
  • exist/trunk/python/ndgUtils/vocabtermdata.py

    r4313 r4347  
    123123                 NEODC_TERM:VocabTermItem('NOT YET SET UP', NEODC_TERM, title = 'NERC Earth Observation Data Centre'), 
    124124                  
    125                  LOGO_TERM:VocabTermItem('LOGO', 'LOGO', title = 'Logo'), 
     125                 LOGO_TERM:VocabTermItem('NOT YET SET UP', LOGO_TERM, title = 'Logo'), 
    126126                 NUM_SIM_TERM:VocabTermItem('http://vocab.ndg.nerc.ac.uk/term/N041', '7', title = 'NumSim description'), 
    127127                 OPENDAP_TERM:VocabTermItem('http://vocab.ndg.nerc.ac.uk/term/P201', 'GCMDU010', title = 'GET DATA &gt; OPENDAP DATA (DODS)'), 
Note: See TracChangeset for help on using the changeset viewer.