0
|
1 from OFS.Folder import Folder
|
|
2 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
|
|
3 from Globals import package_home
|
|
4 from AccessControl import ClassSecurityInfo
|
|
5 import os.path
|
|
6 import urllib
|
|
7 import logging
|
|
8 import urlparse
|
|
9
|
|
10 # TODO: which xml toolkit?
|
|
11 import amara
|
|
12 import xml.sax.saxutils
|
|
13 import xml.dom.minidom
|
|
14 import xml.etree.ElementTree as ET
|
|
15
|
|
16
|
|
17 # TODO: do we need this?
|
|
18 #from Products.OSA_system2 import OSAS_helpers
|
|
19 #from Products.OSA_system2.OSAS_metadata import OSAS_Metadata,OSAS_MetadataMapping
|
|
20
|
2
|
21 from MetaDataMapping import MetaDataMapping
|
0
|
22 from OSAS_metadata import OSAS_Metadata, OSAS_MetadataMapping
|
|
23
|
|
24
|
|
25 from SrvTxtUtils import getHttpData, getText
|
|
26
|
|
27
|
|
28 # TODO: get rid of this
|
|
29 def getTextFromNode(nodelist):
|
|
30 """gibt text aus nodelist"""
|
|
31 rc = ""
|
|
32 for node in nodelist:
|
|
33 if node.nodeType == node.TEXT_NODE:
|
|
34 rc = rc + node.data
|
|
35 return rc
|
|
36
|
|
37
|
|
38 def toString(list):
|
|
39 ret=u""
|
|
40
|
|
41 for l in list:
|
|
42 ret+=unicode(l)
|
|
43
|
|
44 return ret
|
|
45
|
|
46 def dcMetaDataToHash(mdSet):
|
|
47 """Convenience Function for creates a hash from the DCMetadataset
|
|
48 @param mdSet: String containing DCMetadata informmation
|
|
49 currently only in the format getDCMetadata of this module"""
|
|
50
|
|
51 NSS = {
|
|
52 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
|
53 'dc': 'http://dublincore.org/documents/dcmi-namespace/',
|
|
54 'owl':"http://www.w3.org/2002/07/owl#",
|
|
55 'rdfs':"http://www.w3.org/2000/01/rdf-schema#"
|
|
56 }
|
|
57 ret={}
|
|
58 import StringIO
|
|
59 import sys
|
|
60 buffer= StringIO.StringIO(mdSet)
|
|
61 try:
|
|
62 md = amara.parse(buffer,prefixes=NSS)
|
|
63 except:
|
|
64 logging.error("Error: %s (%s)"%(sys.exc_info()[0],sys.exc_info()[1]))
|
|
65
|
|
66 ret["error"]=mdSet
|
|
67 return ret
|
|
68
|
|
69 ret["title"] = toString(md.xml_xpath("//dc:title/text()"))
|
|
70 ret["creator"] =toString(md.xml_xpath("//dc:creator/text()"))
|
|
71 ret["date"] = toString(md.xml_xpath("//dc:date/text()"))
|
|
72
|
|
73 return ret
|
|
74
|
|
75
|
|
76
|
|
77
|
|
78
|
|
79 class MetaData(OSAS_Metadata):
|
|
80 """provides basic methods for managing metadata structures"""
|
|
81 meta_type='MetaData'
|
|
82 security=ClassSecurityInfo()
|
|
83 manage_options = Folder.manage_options+(
|
5
|
84 {'label':'Main Config','action':'changeMetaDataForm'},
|
0
|
85 {'label':'Import XML Schema','action':'importMetaDataExportXML'},
|
3
|
86 #{'label':'Select Fields for Display','action':'indicateDisplayFieldsForm'},
|
0
|
87 )
|
|
88
|
|
89 def __init__(self,id,shortDescription='',description='',fields=''):
|
|
90 """initialize a new instance"""
|
|
91 self.id = id
|
|
92 self.shortDescription =shortDescription #label fuer link auf add page
|
|
93 self.description=description #description of the method for link page
|
|
94 self.fieldList=fields.split(",")[0:]
|
|
95 self.metaDataServerUrl="" # muss mit change metadata gesetzt werden
|
|
96
|
|
97
|
|
98 def correctPath(self,path,remove=None,prefix=None,cut=0):
|
|
99 """convinience method um einen pfad zu veraendern"""
|
|
100 if remove is not None:
|
|
101 path=path.replace(remove,'')
|
|
102 if prefix is not None:
|
|
103 path=os.path.join(prefix,path)
|
|
104
|
|
105 if cut>0:
|
|
106 splitted=path.split("/")
|
|
107 path="/".join(splitted[0:len(splitted)-cut])
|
|
108 return path
|
|
109
|
|
110 def importMetaDataExportXML(self,importFile=None,RESPONSE=None):
|
|
111 """imports metadata from the metadataexportxml file"""
|
|
112
|
|
113 if importFile is None:
|
3
|
114 pt=PageTemplateFile('zpt/importMetaDataExportXML', globals()).__of__(self)
|
0
|
115 return pt()
|
|
116
|
3
|
117 dom=ET.parse(importFile)
|
|
118 node = dom.getroot()
|
|
119 if node.tag != 'metadataExport':
|
|
120 node = dom.find("metadataExport")
|
|
121
|
|
122 self.createMappingFromDom(node)
|
0
|
123
|
|
124 if RESPONSE is not None:
|
|
125 RESPONSE.redirect('manage_main')
|
|
126
|
|
127
|
|
128 def createMappingFromDom(self,metadatanode,metadata=None):
|
|
129 """erzeuge ein Mapping aus dem der metadatanode des xmlformats, metadata ist ein metadataobject"""
|
|
130
|
|
131 if metadata is None:
|
|
132 metadata=self
|
|
133
|
3
|
134 nodes=metadatanode
|
0
|
135
|
|
136 for node in nodes:
|
2
|
137 logging.debug("node: %s"%repr(node))
|
3
|
138 if node.tag=="set":
|
0
|
139 set=node
|
3
|
140 id=set.get('name')
|
|
141 list=[]
|
|
142 argList={}
|
|
143 for entry in set:
|
|
144 genericName=entry.get('genericName')
|
|
145 if set.get('name')=='generic':
|
|
146 # generic mapping doesn't have labels
|
|
147 tag = genericName
|
|
148 label = genericName
|
|
149 else:
|
|
150 tag=entry.get('tag')
|
|
151 label=entry.get('label')
|
|
152
|
|
153 if not tag:
|
|
154 # ignore empty tags
|
|
155 continue
|
|
156
|
|
157 description=getText(entry)
|
|
158 argList[tag]={'tag':tag,'label':label,'explanation':description,'status':'optional'}
|
|
159
|
|
160 logging.debug("createMappingFromDom: new mapping=%s"%repr(argList))
|
|
161 metadata._setObject(id,MetaDataMapping(id,id,argList))
|
|
162
|
|
163 elif node.tag=="metadata":
|
0
|
164 mn=node
|
3
|
165 name=mn.get('name')
|
|
166 logging.debug("createMappingFromDom: new metadata=%s"%repr(name))
|
0
|
167 metadata._setObject(name,MetaData(name,name))
|
|
168 mdObj=getattr(metadata,name)
|
|
169 mdObj.createMappingFromDom(mn)
|
|
170
|
|
171 def getMDFromPathOrUrl(self,path):
|
|
172 parsedurl = urlparse.urlparse(path)
|
|
173 if parsedurl[0] != "":
|
|
174 # has schema (e.g. http)
|
|
175 url=path
|
|
176 else:
|
|
177 # path only
|
|
178 if path.endswith("index.meta"):
|
|
179 url =self.metaDataServerUrl%path
|
|
180 else:
|
|
181 url=os.path.join(self.metaDataServerUrl%path,'index.meta')
|
|
182
|
|
183 #logging.debug("get Metadata: %s"%url)
|
|
184 md = getHttpData(url)
|
|
185 return md
|
|
186
|
|
187 def getDCFormatted(self,path):
|
|
188 """get the metadata as dc set"""
|
|
189 logging.debug("getDCFormatted(path=%s)"%path)
|
|
190 namespace={ 'mpiwg': "http://www.mpiwg-berlin.mpg.de/ns/mpiwg"}
|
|
191 namespaceUsed=False
|
|
192
|
|
193 md = self.getMDFromPathOrUrl(path)
|
|
194 logging.debug("MD in XML"+md)
|
|
195 im = amara.parse(md, prefixes=namespace)
|
|
196
|
|
197 typePaths=im.xml_xpath('//bib/@type')
|
|
198 archimedes=False
|
|
199
|
|
200 if len(typePaths)<1:
|
|
201 typePaths=im.xml_xpath('//meta/archimedes') # sinderfall fuer veraltete index.meta files vom typ archimedes
|
|
202 if len(typePaths)>0:
|
|
203 type = "archimedes"
|
|
204 archimedes=True
|
|
205 else:
|
|
206 typePaths=im.xml_xpath('//mpiwg:bib/@type')
|
|
207 if len(typePaths)<1:
|
|
208 return ""
|
|
209 else:
|
|
210 namespaceUsed=True
|
|
211
|
|
212 type=unicode(typePaths[0])
|
|
213 else:
|
|
214 type=unicode(typePaths[0])
|
|
215 logging.info("got type:"+type)
|
|
216 try:
|
|
217 mapping=getattr(self.main.meta.bib,type.lower(),None)
|
|
218 except:
|
|
219 logging.error("getMetaDataFromServer no mapping for type: %s"%type)
|
|
220 return ""
|
|
221
|
|
222 try:
|
|
223 dcMapping=getattr(self.main.meta.bib,"dc",None)
|
|
224 except:
|
|
225 logging.error("getMetaDataFromServer no dc in meta/bib")
|
|
226 return ""
|
|
227
|
|
228 mds=mapping.generateMappingHash() # Hole das Mapping generisches Feld --> Feld im entsprechenden Typ
|
|
229 dcMds=dcMapping.generateMappingHash()
|
|
230
|
|
231 mdHash=[]
|
|
232 logging.debug("Value: %s"%repr(mds))
|
|
233
|
|
234 for key,valueTriple in mds.items():
|
|
235 value=valueTriple[0]
|
|
236 logging.debug("Value: %s"%repr(value))
|
|
237 logging.debug("Key: %s"%repr(key))
|
|
238 if value!="":
|
|
239 if not archimedes:
|
|
240 if namespaceUsed:
|
|
241 try:
|
|
242 v = im.xml_xpath('//mpiwg:bib/mpiwg:%s/text()'%value)
|
|
243 except:
|
|
244 logging.error('cannot do: //mpiwg:bib/mpiwg:%s/text()'%value)
|
|
245 else:
|
|
246 v = im.xml_xpath('//bib/%s/text()'%value)
|
|
247 else:
|
|
248 v = im.xml_xpath('//archimedes/%s/text()'%value)
|
|
249 if len(v) > 0:
|
|
250 dc=dcMds[key][0]
|
|
251
|
|
252 if (dc !="") and (value !=""):
|
|
253 logging.debug("%s--> : %s"%(repr(value),dc))
|
|
254 mdHash.append([dc,unicode(v[0])])
|
|
255
|
|
256 ret="""<bib xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"> """
|
|
257 ret+="<dc:type>%s</dc:type>"%type
|
|
258 for md in mdHash:
|
|
259
|
|
260 ret+="""<dc:%s>%s</dc:%s>"""%(md[0],xml.sax.saxutils.escape(md[1]),md[0])
|
|
261 ret+="</bib>"
|
|
262 return ret
|
|
263
|
3
|
264
|
|
265 def getBibMapping(self, bibtype):
|
|
266 """returns MetaDataMapping for bibtype"""
|
|
267 # try type as id
|
|
268 mapping = getattr(self.main.meta.bib, bibtype, None)
|
|
269 if mapping is None:
|
|
270 # try manually
|
|
271 mapFolder = self.main.meta.bib
|
|
272 for obj in mapFolder.objectValues():
|
|
273 if obj.meta_type == "MetadataMapping":
|
|
274 # real type is in title
|
|
275 mapType = obj.title
|
|
276 if mapType == bibtype:
|
|
277 # try type as is
|
|
278 return obj
|
|
279
|
|
280 if normalizeBibField(mapType, underscore=True) == normalizeBibField(bibtype, underscore=True):
|
|
281 # try normalized type without underscore
|
|
282 return obj
|
|
283
|
|
284 return mapping
|
0
|
285
|
1
|
286 def getBibFields(self, bibdata):
|
|
287 """returns dict with metadata description for bibdata"""
|
3
|
288 bibfields = {}
|
0
|
289 bibtype = bibdata['@type']
|
|
290 # get mapping from main/meta/bib
|
3
|
291 mapping = self.getBibMapping(bibtype)
|
|
292 if mapping is None:
|
|
293 logging.error("getBibFields: no mapping for type: %s"%bibtype)
|
|
294 return bibfields
|
0
|
295
|
3
|
296 # get field descriptions (copy so we can change it)
|
|
297 bibfields = mapping.getFields().copy()
|
1
|
298 # add field list
|
3
|
299 bibfields['@fieldList'] = mapping.getFieldList()
|
0
|
300
|
3
|
301 return bibfields
|
0
|
302
|
3
|
303 def getBibMappedData(self, bibdata, allFields=False):
|
|
304 """returns dict with metadata descriptions and data for bibdata"""
|
|
305 bibfields = self.getBibFields(bibdata)
|
|
306 mappedData = {}
|
|
307 mappedList = []
|
|
308 for bk in bibfields.keys():
|
|
309 # ignore descriptions without data
|
|
310 if not bibdata.get(bk, None):
|
|
311 continue
|
|
312
|
|
313 # field description (copy so we can change it)
|
|
314 bf = bibfields[bk].copy()
|
|
315 # add value
|
|
316 bf['value'] = bibdata[bk]
|
|
317 mappedData[bk] = bf
|
|
318 mappedList.append(bk)
|
|
319
|
|
320 if allFields and len(mappedData) < len(bibdata):
|
|
321 # add fields that were not in bibfields
|
|
322 for bk in bibdata.keys():
|
|
323 if bk in mappedData or not bibdata[bk]:
|
|
324 continue
|
|
325
|
|
326 mappedData[bk] = {'tag':bk, 'label':bk, 'value':bibdata[bk]}
|
|
327 mappedList.append(bk)
|
|
328
|
|
329 mappedData['@fieldList'] = mappedList
|
|
330 return mappedData
|
0
|
331
|
3
|
332 def getFormatted(self, template, path=None, dom=None, bibdata=None, allFields=False):
|
0
|
333 """returns string with document data formatted according to template.
|
|
334 gets data from server or dom or pre-parsed bibdata."""
|
|
335 logging.debug("getFormatted(template=%s)"%(template))
|
|
336
|
|
337 if dom is None and bibdata is None:
|
|
338 # get from server
|
|
339 md = self.getMDFromPathOrUrl(path.replace("/mpiwg/online",""))
|
|
340 #logging.debug("md:"+md)
|
|
341 #dom = amara.parse(md)
|
|
342 dom = ET.fromstring(md)
|
|
343
|
|
344 # get contents of bib tag
|
|
345 if bibdata is None:
|
|
346 bibdata = getBibdataFromDom(dom)
|
|
347
|
|
348 bibtype = bibdata['@type']
|
|
349
|
|
350 # get template
|
|
351 tp=getattr(self,"%s_%s"%(template, bibtype.lower()), None)
|
|
352 if tp is None:
|
|
353 logging.warning("getFormatted: no template for: %s_%s"%(template, bibtype))
|
|
354 # try generic
|
|
355 tp=getattr(self,"%s_generic"%(template), None)
|
|
356 if tp is None:
|
|
357 logging.error("getFormatted: no generic template either: %s"%(template))
|
|
358 return ""
|
|
359
|
1
|
360 # put bib field descriptions in mdHash
|
3
|
361 bibfields = self.getBibMappedData(bibdata, allFields=allFields)
|
0
|
362
|
3
|
363 return tp(mdmap=bibfields, md=bibdata)
|
0
|
364
|
|
365
|
|
366 def getFormattedMetaData(self, path=None, dom=None, bibdata=None):
|
|
367 """get the metadafrom server"""
|
|
368 logging.debug("getFormattedMetaData(path=%s)"%path)
|
|
369 return self.getFormatted('metadata_template', path=path, dom=dom, bibdata=bibdata)
|
|
370
|
|
371 def getFormattedMetaDataShort(self, path=None, dom=None, bibdata=None):
|
|
372 """get the metadafrom server"""
|
|
373 logging.debug("getFormattedMetaDataShort(path=%s)"%path)
|
|
374 return self.getFormatted('metadata_template', path=path, dom=dom, bibdata=bibdata)
|
|
375
|
|
376 def getFormattedMetaDataExtended(self,path=None, dom=None, bibdata=None):
|
|
377 """get the metadafrom server"""
|
|
378 logging.debug("getFormattedMetaDataExtended(path=%s)"%path)
|
3
|
379 return self.getFormatted('metadata_extended_template', path=path, dom=dom, bibdata=bibdata, allFields=True)
|
0
|
380
|
|
381 def getFormattedLabel(self,path=None, dom=None, bibdata=None):
|
|
382 """get the metadafrom server"""
|
|
383 logging.debug("getFormattedLabel(%s)"%path)
|
|
384 return self.getFormatted('label_template', path=path, dom=dom, bibdata=bibdata)
|
|
385
|
|
386 def getFormattedMetaDataShortFromServer(self,path):
|
|
387 """get the metadafrom server"""
|
|
388 logging.debug("getFormattedMetaDataShortFromServer(path=%s)"%path)
|
|
389 return self.getFormatted('metadata_template', path)
|
|
390
|
|
391 def getFormattedMetaDataExtendedFromServer(self,path):
|
|
392 """get the metadafrom server"""
|
|
393 logging.debug("getFormattedMetaDataExtendedFromServer(path=%s)"%path)
|
3
|
394 return self.getFormatted('metadata_extended_template', path=path, allFields=True)
|
0
|
395
|
|
396 def getFormattedLabelFromServer(self,path):
|
|
397 """get the metadafrom server"""
|
|
398 logging.debug("getFormattedLabelFromServer(%s)"%path)
|
|
399 return self.getFormatted('label_template', path)
|
|
400
|
|
401
|
5
|
402 security.declarePublic('changeMetaDataForm')
|
|
403 def changeMetaDataForm(self):
|
0
|
404 """Main configuration"""
|
5
|
405 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMetaData.zpt')).__of__(self)
|
0
|
406 return pt()
|
|
407
|
5
|
408 security.declarePublic('changeMetaData')
|
|
409 def changeMetaData(self,shortDescription,description,fields,metaDataServerUrl,RESPONSE=None):
|
0
|
410 """Change Metadata"""
|
|
411 self.shortDescription=shortDescription
|
|
412 self.description=description
|
|
413 self.fieldList=fields.split(",")[0:]
|
|
414 self.metaDataServerUrl=metaDataServerUrl
|
|
415 if RESPONSE is not None:
|
|
416 RESPONSE.redirect('manage_main')
|
|
417
|
|
418
|
|
419 def manage_addMetaDataForm(self):
|
|
420 """interface for adding the OSAS_add_Metadata"""
|
5
|
421 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetaDataForm.zpt')).__of__(self)
|
0
|
422 return pt()
|
|
423
|
|
424 def manage_addMetaData(self,id,shortDescription,description,fields,RESPONSE=None):
|
|
425 """a metadata objekt"""
|
|
426 newObj=MetaData(id,shortDescription,description,fields)
|
|
427 self.Destination()._setObject(id,newObj)
|
|
428 if RESPONSE is not None:
|
|
429 RESPONSE.redirect('manage_main')
|
|
430
|