Coverage for gws-app/gws/plugin/ows_server/csw/templates/iso/record.py: 94%

67 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-16 23:09 +0200

1""" "CSW Record template (gmd:MD_Metadata, ISO).""" 

2 

3import gws 

4import gws.base.ows.server as server 

5import gws.base.ows.server.templatelib as tpl 

6 

7ML_GMX_CODELISTS = 'http://standards.iso.org/iso/19139/resources/gmxCodelists.xml' 

8 

9 

10def record(ta: server.TemplateArgs, md: gws.Metadata): 

11 def w_code(wrap, lst, value, text=None): 

12 return ( 

13 f'gmd:{wrap}/gmd:{lst}', 

14 {'codeList': ML_GMX_CODELISTS + '#' + lst, 'codeListValue': value}, 

15 text or value, 

16 ) 

17 

18 def w_date(d, typ): 

19 return ( 

20 'gmd:date/gmd:CI_Date', 

21 ('gmd:date/gco:Date', tpl.iso_date(d)), 

22 w_code( 

23 'dateType', 

24 'CI_DateTypeCode', 

25 typ, 

26 ), 

27 ) 

28 

29 def w_lang(): 

30 return ( 

31 'gmd:language/gmd:LanguageCode', 

32 {'codeList': 'http://www.loc.gov/standards/iso639-2/', 'codeListValue': md.language3}, 

33 md.languageName, 

34 ) 

35 

36 def w_bbox(ext): 

37 return ( 

38 'gmd:EX_GeographicBoundingBox', 

39 ('gmd:westBoundLongitude/gco:Decimal', tpl.coord_dms(ext[0])), 

40 ('gmd:eastBoundLongitude/gco:Decimal', tpl.coord_dms(ext[2])), 

41 ('gmd:southBoundLatitude/gco:Decimal', tpl.coord_dms(ext[1])), 

42 ('gmd:northBoundLatitude/gco:Decimal', tpl.coord_dms(ext[3])), 

43 ) 

44 

45 def contact(): 

46 yield ( 

47 'gmd:CI_ResponsibleParty', 

48 ('gmd:organisationName/gco:CharacterString', md.contactOrganization), 

49 ('gmd:positionName/gco:CharacterString', md.contactPosition), 

50 ( 

51 'gmd:contactInfo/gmd:CI_Contact', 

52 ( 

53 'gmd:phone/gmd:CI_Telephone', 

54 ('gmd:voice/gco:CharacterString', md.contactPhone), 

55 ('gmd:facsimile/gco:CharacterString', md.contactFax), 

56 ), 

57 ( 

58 'gmd:address/gmd:CI_Address', 

59 ('gmd:deliveryPoint/gco:CharacterString', md.contactAddress), 

60 ('gmd:city/gco:CharacterString', md.contactCity), 

61 ('gmd:administrativeArea/gco:CharacterString', md.contactArea), 

62 ('gmd:postalCode/gco:CharacterString', md.contactZip), 

63 ('gmd:country/gco:CharacterString', md.contactCountry), 

64 ('gmd:electronicMailAddress/gco:CharacterString', md.contactEmail), 

65 ), 

66 ('gmd:onlineResource/gmd:CI_OnlineResource/gmd:linkage/gmd:URL', md.contactUrl), 

67 ), 

68 w_code('role', 'CI_RoleCode', md.contactRole), 

69 ) 

70 

71 def identification(): 

72 yield ( 

73 'gmd:citation/gmd:CI_Citation', 

74 ('gmd:title/gco:CharacterString', md.title), 

75 w_date(md.dateCreated, 'publication'), 

76 w_date(md.dateUpdated, 'revision'), 

77 ('gmd:identifier/gmd:MD_Identifier/gmd:code/gco:CharacterString', md.catalogCitationUid), 

78 ) 

79 

80 yield 'gmd:abstract/gco:CharacterString', md.abstract 

81 

82 yield 'gmd:pointOfContact', contact() 

83 

84 if md.inspireSpatialScope: 

85 lst = 'http://inspire.ec.europa.eu/metadata-codelist/SpatialScope/' 

86 yield ( 

87 'gmd:descriptiveKeywords/gmd:MD_Keywords', 

88 ('gmd:keyword/gmx:Anchor', {'xlink:href': lst + md.inspireSpatialScope}, md.inspireSpatialScopeName), 

89 ( 

90 'gmd:thesaurusName/gmd:CI_Citation', 

91 ('gmd:title/gmx:Anchor', {'xlink:href': lst + 'SpatialScope'}, 'Spatial scope'), 

92 w_date('2019-05-22', 'publication'), 

93 ), 

94 ) 

95 

96 if md.inspireTheme: 

97 yield ( 

98 'gmd:descriptiveKeywords/gmd:MD_Keywords', 

99 ('gmd:keyword/gco:CharacterString', md.inspireThemeNameEn), 

100 w_code('type', 'MD_KeywordTypeCode', 'theme'), 

101 ( 

102 'gmd:thesaurusName/gmd:CI_Citation', 

103 ('gmd:title/gco:CharacterString', 'GEMET - INSPIRE themes, version 1.0'), 

104 w_date('2008-06-01', 'publication'), 

105 ), 

106 ) 

107 

108 if md.keywords: 

109 yield ( 

110 'gmd:descriptiveKeywords/gmd:MD_Keywords', 

111 [('gmd:keyword/gco:CharacterString', kw) for kw in md.keywords], 

112 ) 

113 

114 yield ( 

115 'gmd:resourceConstraints/gmd:MD_LegalConstraints', 

116 w_code('useConstraints', 'MD_RestrictionCode', 'otherRestrictions'), 

117 ('gmd:otherConstraints/gco:CharacterString', md.accessConstraints), 

118 ('gmd:otherConstraints/gco:CharacterString', md.license), 

119 ) 

120 

121 yield w_code( 

122 'spatialRepresentationType', 

123 'MD_SpatialRepresentationTypeCode', 

124 md.isoSpatialRepresentationType, 

125 ) 

126 

127 if md.isoSpatialResolution: 

128 yield ( 

129 'gmd:spatialResolution/gmd:MD_Resolution/gmd:equivalentScale/gmd:MD_RepresentativeFraction/gmd:denominator/gco:Integer', 

130 md.isoSpatialResolution, 

131 ) 

132 

133 yield w_lang() 

134 yield w_code('characterSet', 'MD_CharacterSetCode', 'utf8') 

135 

136 if md.isoTopicCategories: 

137 for cat in md.isoTopicCategories: 

138 yield 'gmd:topicCategory/gmd:MD_TopicCategoryCode', cat 

139 

140 if md.wgsExtent: 

141 yield 'gmd:extent/gmd:EX_Extent/gmd:geographicElement', w_bbox(md.wgsExtent) 

142 

143 # @TODO 

144 # if md.bounding_polygon_element: 

145 # yield ( 

146 # 'gmd:extent/gmd:EX_Extent/gmd:geographicElement/gmd:EX_BoundingPolygon/gmd:polygon', 

147 # md.bounding_polygon_element 

148 # ) 

149 

150 if md.temporalBegin: 

151 yield ( 

152 'gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod', 

153 ('gml:beginPosition', md.temporalBegin), 

154 ('gml:endPosition', md.temporalEnd), 

155 ) 

156 

157 def distributionInfo(): 

158 for link in md.metaLinks: 

159 if link.format: 

160 yield ( 

161 'gmd:distributionFormat/gmd:MD_Format', 

162 ('gmd:name/gco:CharacterString', link.format), 

163 ('gmd:version/gco:CharacterString', link.formatVersion), 

164 ) 

165 

166 for link in md.metaLinks: 

167 yield ( 

168 'gmd:transferOptions/gmd:MD_DigitalTransferOptions', 

169 ( 

170 'gmd:onLine/gmd:CI_OnlineResource', 

171 ('gmd:linkage/gmd:URL', ta.url_for(link.url)), 

172 w_code('function', 'CI_OnLineFunctionCode', link.function), 

173 ), 

174 ) 

175 

176 def dataQualityInfo(): 

177 yield 'gmd:scope/gmd:DQ_Scope', w_code('level', 'MD_ScopeCode', md.isoScope) 

178 

179 if md.isoQualityConformanceQualityPass: 

180 yield ( 

181 'gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult', 

182 ( 

183 'gmd:specification/gmd:CI_Citation', 

184 ('gmd:title/gco:CharacterString', md.isoQualityConformanceSpecificationTitle), 

185 w_date(md.isoQualityConformanceSpecificationDate, 'publication'), 

186 ), 

187 ('gmd:explanation/gco:CharacterString', md.isoQualityConformanceExplanation), 

188 ('gmd:pass/gco:Boolean', md.isoQualityConformanceQualityPass), 

189 ) 

190 

191 if md.isoQualityLineageStatement: 

192 yield ( 

193 'gmd:lineage/gmd:LI_Lineage', 

194 ('gmd:statement/gco:CharacterString', md.isoQualityLineageStatement), 

195 ( 

196 'gmd:source/gmd:LI_Source', 

197 ('gmd:description/gco:CharacterString', md.isoQualityLineageSource), 

198 ('gmd:scaleDenominator/gmd:MD_RepresentativeFraction/gmd:denominator/gco:Integer', md.isoQualityLineageSourceScale), 

199 ), 

200 ) 

201 

202 def content(): 

203 yield 'gmd:fileIdentifier/gco:CharacterString', md.catalogUid 

204 

205 w_lang() 

206 yield w_code('characterSet', 'MD_CharacterSetCode', 'utf8') 

207 

208 yield w_code('hierarchyLevel', 'MD_ScopeCode', md.isoScope) 

209 yield 'gmd:hierarchyLevelName/gco:CharacterString', md.isoScopeName 

210 

211 yield 'gmd:contact', contact() 

212 

213 yield 'gmd:dateStamp/gco:Date', tpl.iso_date(md.dateUpdated) 

214 

215 yield 'gmd:metadataStandardName/gco:CharacterString', 'ISO19115' 

216 yield 'gmd:metadataStandardVersion/gco:CharacterString', '2003/Cor.1:2006' 

217 

218 if md.crs: 

219 yield ( 

220 'gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:code/gco:CharacterString', 

221 md.crs.uri, 

222 ) 

223 

224 yield 'gmd:identificationInfo/gmd:MD_DataIdentification', identification() 

225 yield 'gmd:distributionInfo/gmd:MD_Distribution', distributionInfo() 

226 yield 'gmd:dataQualityInfo/gmd:DQ_DataQuality', dataQualityInfo() 

227 

228 ## 

229 

230 return 'gmd:MD_Metadata', content()