Annotation of OSA_system2/OSAS_metadata.py, revision 1.15
1.1 dwinter 1: """ Classes for managing metadata"""
2:
3: from OFS.SimpleItem import SimpleItem
4: from Globals import InitializeClass,package_home
5: from OFS.Folder import Folder
6: from AccessControl import ClassSecurityInfo
7: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
8: import os.path
1.5 dwinter 9: import sys
1.1 dwinter 10: import xml.dom.minidom
1.4 dwinter 11: import xml.dom.pulldom
1.1 dwinter 12: import OSAS_helpers
13: import zLOG
1.4 dwinter 14: import string
1.8 dwinter 15: try:
16: from xml.xpath import Evaluate
17: except:
18: from Ft.Xml.XPath import Evaluate
1.4 dwinter 19: import xmlrpclib
20:
21: from types import *
1.1 dwinter 22:
23: class OSAS_MetadataMapping(SimpleItem):
24: """Einfaches Mapping Object"""
25:
26: meta_type="OSAS_MetadataMapping__neu"
27:
28: def readFieldsFromParent(self):
29: """read all elements from root"""
30:
31: return self.aq_parent.fieldList
32:
33: def __init__(self,id,title,arglist):
34: """init
35: @param id: id
36: @param title: title fuer zope navigation
37: @param arglist: dictionary mit Namen der zugelassenen generische Metadaten als key und Tripel als Werte (human readable, tag version,explanation
38: """
39: self.id=id
40: self.title=title
41: for fieldName in arglist.keys():
42: setattr(self,"md_"+fieldName,arglist[fieldName])
43:
1.9 dwinter 44:
1.1 dwinter 45: manage_options = SimpleItem.manage_options+(
46: {'label':'Main Config','action':'changeMetadataMappingForm'},
47: )
48:
49:
50: def showSetXML(self,RESPONSE=None):
51: """prints out the mapping as XML"""
52: ret="""<set name="%s">"""%self.title
53: for fieldName in self.readFieldsFromParent():
54: entry=getattr(self,"md_"+fieldName)
55: if entry[2]=="": # no explanation of this field
56: ret+="""<entry genericName="%s" tag="%s" label="%s"/>"""%(fieldName,entry[0],entry[1])
57: else:
58: ret+="""<entry genericName="%s" tag="%s" label="%s">%s</entry>"""%(fieldName,entry[0],entry[1],entry[2])
59: ret+="</set>"
60:
61: if not RESPONSE:
62: return ret
63: else:
64: self.REQUEST.RESPONSE.setHeader('Content-Type','text/xml')
65: return ret
66:
67: def getValue(self,fieldName):
68: """get md value
69: @param fieldName: Bezeichnung des gesuchten Metadatums
70: @retunr: Value des Metadatums"""
1.4 dwinter 71:
72: ret= getattr(self,"md_"+fieldName,(None,None,None,None,None))
73: if len(ret)!= 4: # alte MD haben keine info ueber optional/required und listen werte
74: ret=ret+("","")
75: return ret
76:
1.1 dwinter 77:
78: def isEmptyValue(self,fieldName):
79: """teste ob fielname in diesem Metadatenschema definiert ist"""
80: field=getattr(self,"md_"+fieldName,'')
81: if field[1]=='':
82: return 0
83: else:
84: return 1
85:
86: def generateMappingHash(self):
87: """erzeugen des dictionaries: generisches Feld -> Definition in diesem Schema"""
88: hash={}
89: for field in self.fieldList:
90: hash[field]=getattr(self,"md_"+field)
91: return hash
92:
93:
94:
95: def changeMetadataMappingForm(self):
96: """change"""
97: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMetadataMapping.zpt')).__of__(self)
98: return pt()
99:
100: def changeMetadataMapping(self,titleOfObject,RESPONSE=None):
101: """change"""
102:
103: self.title=titleOfObject
104: arglist=self.REQUEST.form
105:
106: for fieldName in self.readFieldsFromParent():
1.4 dwinter 107: setattr(self,"md_"+fieldName,(arglist[fieldName],arglist['label_'+fieldName],arglist['explanation_'+fieldName],arglist['status_'+fieldName],arglist['values_'+fieldName]))
1.1 dwinter 108:
109:
110: if RESPONSE is not None:
111: RESPONSE.redirect('manage_main')
112:
1.10 dwinter 113: manage_workspace=changeMetadataMappingForm
1.1 dwinter 114:
115: def manage_addMetadataMappingForm(self):
116: """interface for adding the OSAS_root"""
117: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataMappingForm.zpt')).__of__(self)
118:
119: return pt()
120:
121: def manage_addMetadataMapping(self,idOfObject,titleOfObject,RESPONSE=None):
122: """add the OSAS_root"""
123:
124: argList={}
125: for arg in self.fieldList:
126: if not (arg in ['idOfObject','titleOfObject']):
1.12 casties 127: argList[arg]=(self.REQUEST.form[arg],self.REQUEST.form['label_'+arg],self.REQUEST.form['explanation_'+arg],self.REQUEST.form['status_'+arg],self.REQUEST.form['values_'+arg])
1.1 dwinter 128:
129: newObj=OSAS_MetadataMapping(idOfObject,titleOfObject,argList)
130: self._setObject(idOfObject,newObj)
131: if RESPONSE is not None:
132: RESPONSE.redirect('manage_main')
133:
134:
135:
136: class OSAS_Metadata(Folder):
137: """Foldertype enthält methoden zur Halbautomatischen Erstellung von Metadatenfiles"""
138: security=ClassSecurityInfo()
139:
1.4 dwinter 140: def __init__(self,id,shortDescription,description,fields):
1.1 dwinter 141: """initialize a new instance"""
142: self.id = id
1.4 dwinter 143: self.shortDescription =shortDescription #label fuer link auf add page
1.1 dwinter 144: self.description=description #description of the method for link page
145: self.fieldList=fields.split(",")[0:]
146:
147: meta_type='OSAS_Metadata__neu'
148:
149: manage_options = Folder.manage_options+(
150: {'label':'Main Config','action':'changeMetadataForm'},
151: {'label':'Import XML Schema','action':'importXMLSchemaForm'},
152: {'label':'Select Fields for Display','action':'indicateDisplayFieldsForm'},
153: )
154:
155: def showGenericXML(self,RESPONSE=None):
156: """show generic fields as XML"""
157: ret="""<set name="%s">"""%"generic"
158: for field in self.fieldList:
159: ret+="""<entry genericName="%s"/>"""%field
160:
161: ret+="</set>"
162:
163: if not RESPONSE:
164: return ret
165: else:
166: self.REQUEST.RESPONSE.setHeader('Content-Type','text/xml')
167: return ret
168:
169: def showOverviewXML(self,RESPONSE):
170: """gives an overview over the Metadata stored in this folder"""
171: ret="""<metadata name="%s">"""%self.getId()
172: ret+=self.showGenericXML()
173: for entry in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping']):
174: ret+=entry[1].showSetXML()
175:
176: ret+="</metadata>"
177:
178: if not RESPONSE:
179: return ret
180: else:
181: self.REQUEST.RESPONSE.setHeader('Content-Type','text/xml')
182: return ret
183:
184: def generateMappingList(self):
185: """Erzeuge Mapping"""
186: mapping={}
1.10 dwinter 187:
1.1 dwinter 188: for dict in self.__dict__:
189: #print dict
190: obj=getattr(self,dict)
191: if hasattr(obj,'meta_type'):
1.10 dwinter 192: if obj.meta_type=="OSAS_MetadataMapping__neu":
1.1 dwinter 193: mapping[obj.getId()]=obj.generateMappingHash()
1.10 dwinter 194:
1.1 dwinter 195: return mapping
196:
197: def generateMappingForType(self,type,clean="yes"):
198: """erzeuge spezifisches Mapping"""
1.10 dwinter 199:
1.1 dwinter 200: hash=self.generateMappingList()
201:
1.10 dwinter 202: for key in hash.keys():
203: if (key.lower() == type.lower()):
204: if clean=="yes":
205: temp={}
206: for x in hash[key].keys():
207: if not hash[key][x]=="":
208: temp[x]=hash[key][x]
209: return temp
210: else:
211:
212: return hash[key]
213:
214: return {}
1.1 dwinter 215:
216: def getFieldList(self):
217: """erzeuge string aus fields"""
218: try:
219: return string.join(self.fieldList,",")
220: except:
221: return ""
222:
1.12 casties 223: security.declarePublic('getFields')
1.1 dwinter 224: def getFields(self):
225: """ausgabe der Felder"""
226: return self.fieldList
227:
228: def getTypeTitle(self,id):
229: """Title von ID"""
230: try:
231: obj=getattr(self,id)
232: return obj.title
233: except:
234: return id
1.4 dwinter 235:
236: def getType(self,type):
237: """gib metadataobject type zurueck"""
238:
239: for obj in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping__neu']):
240: if obj[0]==type:
241: return obj
242: return (self.id,self)
243:
244:
1.1 dwinter 245:
246: def getStoredTypes(self):
247: """Gebe gespeicherte typen zurück"""
248:
249: types=[]
250:
1.13 dwinter 251: for obj in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping__neu']):
252: if obj[1].title=="":
253: title=obj[1].id
254: else:
255: title=obj[1].title
256: types.append((obj[1].id, title, obj[1]))
1.1 dwinter 257:
258: return types
259:
260: def indicateDisplayFieldsForm(self):
261: """form zur Makierung der Felder die in der Browserumgebung angezeigt werden"""
262: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','indicateDisplayFieldsForm.zpt')).__of__(self)
263: return pt()
264:
265: def indicateDisplayFields(self,displayFields,RESPONSE=None):
266: """set Displayfields
267: @param displayFields: Liste von Felder die im Browserenvironment angezeigt werden
268: """
269: self.displayFields=OSAS_helpers.toList(displayFields)
270: if RESPONSE is not None:
271: RESPONSE.redirect('manage_main')
272:
1.3 dwinter 273: def getDisplayFieldsAsStr(self,indexMeta):
1.4 dwinter 274: ret=[]
1.9 dwinter 275: try:
1.6 dwinter 276: if indexMeta and not (indexMeta==""):
1.5 dwinter 277: dom=xml.dom.pulldom.parseString(indexMeta)
1.4 dwinter 278:
1.5 dwinter 279: for (event,node) in dom:
1.4 dwinter 280:
1.5 dwinter 281: if event == xml.dom.pulldom.START_ELEMENT and node.tagName=="bib":
282: dom.expandNode(node)
1.4 dwinter 283:
1.5 dwinter 284: try:
285: type=node.getAttribute('type')
286: mapping=getattr(self,type).generateMappingHash()
287: except:
288: type='generic'
289: mapping=getattr(self,type).generateMappingHash()
1.4 dwinter 290:
1.5 dwinter 291: for field in self.displayFields:
292: try:
293: ret.append(OSAS_helpers.getText(node.getElementsByTagName(mapping[field][0])[0].childNodes))
294: except:
295: """nothing"""
1.4 dwinter 296:
1.5 dwinter 297: return "; ".join(ret)
1.6 dwinter 298: else:
1.5 dwinter 299: return ""
1.9 dwinter 300: except:
301: return ""
1.4 dwinter 302: def getDisplayFieldsAsStrOLD(self,indexMeta):
1.1 dwinter 303: """Gebe display fields als string zurück
304: @param path: Pfad zum Object
305: """
306: ret=[]
307: try:
1.3 dwinter 308: dom=xml.dom.minidom.parseString(indexMeta)
1.1 dwinter 309: except:
1.3 dwinter 310: zLOG.LOG("OSAS_metadata (getDisplayFieldsAsStr)",zLOG.INFO,"Cannot parse: %s"%indexMeta)
1.1 dwinter 311: try:
312: bib = dom.getElementsByTagName("meta")[0].getElementsByTagName("bib")[0]
313: except:
314: return ""
315: try:
316: type=bib.getAttribute('type')
317: mapping=getattr(self,type).generateMappingHash()
318: except:
319: type='generic'
320: mapping=getattr(self,type).generateMappingHash()
321:
322: for field in self.displayFields:
323: try:
324: ret.append(OSAS_helpers.getText(bib.getElementsByTagName(mapping[field][0])[0].childNodes))
325: except:
326: """nothing"""
327:
328: return "; ".join(ret)
329:
330: security.declarePublic('changeMetadataForm')
331: def changeMetadataForm(self):
332: """Main configuration"""
333: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMetadata.zpt')).__of__(self)
334: return pt()
335:
336: security.declarePublic('changeMetadata')
1.4 dwinter 337: def changeMetadata(self,shortDescription,description,fields,RESPONSE=None):
1.1 dwinter 338: """Change Metadata"""
1.4 dwinter 339: self.shortDescription=shortDescription
1.1 dwinter 340: self.description=description
341: self.fieldList=fields.split(",")[0:]
342: if RESPONSE is not None:
343: RESPONSE.redirect('manage_main')
344:
345: security.declarePublic('index_html')
346:
347: def importXMLSchemaForm(self):
348: """form"""
349: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','importXMLSchemaForm.zpt')).__of__(self)
350: return pt()
351:
1.4 dwinter 352:
1.1 dwinter 353: def importXMLSchema(self,file,RESPONSE=None):
354: """import xmlschema, Metadatenschema wird eingelesen und entsprechende Metadatenmappings angelegt."""
355:
356: dom=xml.dom.minidom.parse(file)
357: sets=dom.getElementsByTagName('set')
358: #erster schritt: anlegen der fieldlist
359: for set in sets:
360: if set.getAttribute('name')=='generic':
361: list=[]
362: for entry in set.getElementsByTagName('entry'):
363: list.append(entry.getAttribute('genericName'))
364: self.fieldList=list[0:]
365:
366: #zweiter schritt: anlegen der mapping
367: for set in sets:
368: id=set.getAttribute('name').encode('utf-8')
369: list=[]
370: argList={}
371: for entry in set.getElementsByTagName('entry'):
372: genericName=entry.getAttribute('genericName')
373: tag=entry.getAttribute('tag')
374: label=entry.getAttribute('label')
375: description=OSAS_helpers.getText(entry.childNodes)
376: argList[genericName]=(tag,label,description)
377: self._setObject(id,OSAS_MetadataMapping(id,id,argList))
378: if RESPONSE:
379: RESPONSE.write("Wrote: %s"%id)
1.4 dwinter 380:
381:
382: def createMetadataFragment(self,type,path,prefix="",presets={}):
383: """fragment"""
384: self.REQUEST.SESSION['MDF_type']=type
385: self.REQUEST.SESSION['MDF_path']=path
386: self.REQUEST.SESSION['MDF_prefix']=prefix
387: self.REQUEST.SESSION['MDF_presets']=presets
388:
389: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm_fragment.zpt')).__of__(self)
390: return pt()
391:
392: def createMetadataForm(self,type="",path=""):
393: """createMetadataForm"""
394: self.REQUEST.SESSION['MDF_type']=type
395: self.REQUEST.SESSION['MDF_path']=path
396:
397:
398: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm_template.zpt')).__of__(self)
399: return pt()
400:
1.7 dwinter 401: def readMetadata(self,MDF_path,MDF_type,MDF_prefix="",MDF_xpathStart="", MDF_addPath=None,MDF_identifyFields=None,newdoc=None,actualNode=None):
402:
403: if type(MDF_path)==ListType:
404: MDF_path=MDF_path[0]
405:
406: indexFile=os.path.join(MDF_path,'index.meta')
407:
408: server=xmlrpclib.Server(self.serverUrl)
409:
410: documentStr=server.getFile(indexFile)
411:
412: if documentStr:
413: newdoc=xml.dom.minidom.parseString(documentStr)
414: dom=newdoc.documentElement
415: actualNode=dom
416: else:
417: return {}
418:
419: if self.containerTag=="":
420: containerTag="doc"
421: else:
422: containerTag=self.containerTag
423:
424: if MDF_xpathStart=="":
425: dom=newdoc.documentElement
426: actualNode=dom
427: else:
428: #try to find xpath
429: if MDF_identifyFields:
430: query=[]
431: for field in MDF_identifyFields.keys():
432:
433: query.append("""(%s="%s")"""%(field,MDF_identifyFields[field]))
434: querystr=" and ".join(query)
435: xpathStr=MDF_xpathStart+"[%s]"%querystr
436:
437: else:
438: xpathStr=MDF_xpathStart
439:
440:
1.8 dwinter 441: xpathNodes=Evaluate(xpathStr,actualNode)
1.7 dwinter 442:
443:
444: if len(xpathNodes)>0:
445: actualNode=xpathNodes[0]
446: else:
447: return {}
448:
449: ret={}
450: for node in actualNode.childNodes:
451: name=node.tagName
452: text=OSAS_helpers.getText(node.childNodes)
453: ret[name]=text
454:
455: return ret
456:
1.4 dwinter 457: def writeMetadata(self,MDF_path,MDF_type,form,MDF_prefix="",MDF_xpathStart="", MDF_addPath=None,MDF_identifyFields=None,newdoc=None,actualNode=None):
458: """writeMetadata"""
459: #MDF_path="/tmp/index.meta"
460: if type(MDF_path)==ListType:
461: MDF_path=MDF_path[0]
462:
1.7 dwinter 463:
1.4 dwinter 464: indexFile=os.path.join(MDF_path,'index.meta')
1.7 dwinter 465:
1.4 dwinter 466: server=xmlrpclib.Server(self.serverUrl)
467: if newdoc:
468: if not actualNode: actualNode=newdoc
469: dom=newdoc
470: else:
471: documentStr=server.getFile(indexFile)
1.5 dwinter 472:
1.4 dwinter 473: if documentStr:
1.5 dwinter 474:
1.4 dwinter 475: newdoc=xml.dom.minidom.parseString(documentStr)
476: dom=newdoc.documentElement
477: actualNode=dom
478:
479:
480: else:
1.5 dwinter 481:
1.4 dwinter 482: impl=xml.dom.minidom.getDOMImplementation()
483: newdoc=None
484:
485:
486: if self.containerTag=="":
487: containerTag="doc"
488: else:
489: containerTag=self.containerTag
490:
491: create=None
492: if MDF_xpathStart=="":
493: if not newdoc:
494: newdoc=impl.createDocument(None,containerTag,None)
495: dom=newdoc.documentElement
496: actualNode=dom
497: else:
498:
499: #try to find xpath
500: if MDF_identifyFields:
501: query=[]
502: for field in MDF_identifyFields:
503:
504: query.append("""(%s="%s")"""%(field,form[MDF_prefix+"MD_"+field]))
505: querystr=" and ".join(query)
506: xpathStr=MDF_xpathStart+"[%s]"%querystr
507:
508: else:
509: xpathStr=MDF_xpathStart
510:
1.5 dwinter 511:
1.8 dwinter 512: xpathNodes=Evaluate(xpathStr,actualNode)
1.4 dwinter 513:
514:
515:
516:
517: if len(xpathNodes)>0:
518: actualNode=xpathNodes[0]
519:
520: else:
521: #existiert nicht dann neue erzeugen
522:
1.8 dwinter 523: if len(Evaluate(MDF_xpathStart,dom))>0:
1.4 dwinter 524:
525: create=True
526:
527: splitted=MDF_xpathStart.split("/")
528: base=""
529: for element in splitted:
530:
531: if not (element=="") and not (element==containerTag):
532: base="/".join([base,element])
533:
534: if not newdoc:
535: newdoc=impl.createDocument(None,element,None)
536: actualNode=newdoc.documentElement
537: dom=actualNode
538: else:
539: changed=None
540:
541: if not (MDF_addPath==base):
542:
543:
544: for childNode in actualNode.childNodes:
545: if getattr(childNode,'tagName','')==element:
546: actualNode=childNode
547: changed=1
548:
549: if (os.path.normpath("/".join(["",containerTag,base]))==MDF_xpathStart) and create:
550: actualNode=actualNode.parentNode
551: changed=None
552:
553: if not changed:
554: namenode=newdoc.createElement(element)
555:
556: actualNode.appendChild(namenode)
557: actualNode=namenode
558:
559:
560:
561:
562: for name in self.REQUEST.form.keys():
563: length=len(MDF_prefix)
564: if MDF_type and not (MDF_type == ""):
565: actualNode.setAttribute("type",MDF_type)
566: if name[0:3+length]==MDF_prefix+"MD_":
567: tagName=name[3+length:]
568:
569: #CHECK if element exists
570: for childNode in actualNode.childNodes:
571: if getattr(childNode,'tagName','')==tagName:
572: actualNode.removeChild(childNode).unlink()
573:
574: namenode=newdoc.createElement(tagName)
575: namenodetext=newdoc.createTextNode(self.REQUEST.form[name])
576: namenode.appendChild(namenodetext)
577: actualNode.appendChild(namenode)
578:
579: ret=newdoc.toxml(encoding='utf-8')
1.14 dwinter 580: zLOG.LOG("OSAS_metadata (writeMetadata)",zLOG.INFO,"write: %s"%ret)
1.13 dwinter 581:
1.4 dwinter 582:
583: server.writeMetaDataFile(indexFile,ret)
584:
585:
586: return newdoc,actualNode
587:
588: def writeMetadataFile(self,MDF_path,MDF_type,MDF_xpathStart="",newdoc=None,actualNode=None):
589: """writeMetaFile"""
590:
591: return self.writeMetadata(MDF_path,MDF_type,self.REQUEST.form,MDF_xpathStart=MDF_xpathStart,newdoc=newdoc,actualNode=actualNode)
592:
1.1 dwinter 593:
1.4 dwinter 594: def isEmptyValue(self,fieldName):
595: """im generischen fall stets falsch"""
596: return 1
597:
598: def getValue(self,fieldName):
599: """im generischen fall gleich fieldname"""
600: return fieldName,fieldName,"","",""
601:
602: def getList(self,list):
603: """return list"""
604:
605: if list=="":
606: return None
1.15 ! casties 607: listsplit=[i.rstrip() for i in list.split("\n")]
1.4 dwinter 608: return listsplit
609:
610: def showHelp(self,refType,genericTag):
611: """helptext"""
612: for reference in self.ZopeFind(self):
613: if reference[1].title==refType:
614: text=getattr(reference[1],'md_'+genericTag)[2]
615: return text
616: return "NO EXPLANATION"
617:
618: def showHelpTag(self,url,reftype,item):
619: """gen javascript for showhelp"""
620: url2=url+'/showHelp?refType=%s&genericTag=%s'%(reftype,item)
621: ret="""javascript:wd=window.open(\'%s\',\'Help\',\'width=300,height=250\');void(\'\');wd.focus();"""%url2
622: return ret
623:
624:
1.1 dwinter 625: def manage_addMetadataForm(self):
626: """interface for adding the OSAS_add_Metadata"""
627: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm.zpt')).__of__(self)
628: return pt()
629:
1.4 dwinter 630: def manage_addMetadata(self,id,shortDescription,description,fields,RESPONSE=None):
1.1 dwinter 631: """add the OSAS_root"""
1.4 dwinter 632: newObj=OSAS_Metadata(id,shortDescription,description,fields)
1.1 dwinter 633: self.Destination()._setObject(id,newObj)
634: if RESPONSE is not None:
635: RESPONSE.redirect('manage_main')
636:
637:
638: InitializeClass(OSAS_Metadata)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>