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