Annotation of OSA_system2/OSAS_metadata.py, revision 1.9
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:
113:
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.4 dwinter 127: argList[arg]=(self.REQUEST.form[arg],self.REQUEST.form['label_'+arg],self.REQUEST.form['explanation_'+arg],arglist['status_'+fieldName],arglist['values_'+fieldName])
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={}
187: for dict in self.__dict__:
188: #print dict
189: obj=getattr(self,dict)
190: if hasattr(obj,'meta_type'):
191: if obj.meta_type=="OSAS_MetadataMapping":
192: mapping[obj.getId()]=obj.generateMappingHash()
193: return mapping
194:
195: def generateMappingForType(self,type,clean="yes"):
196: """erzeuge spezifisches Mapping"""
197: hash=self.generateMappingList()
198: if hash.has_key(type):
199: if clean=="yes":
200: temp={}
201: for x in hash[type].keys():
202: if not hash[type][x]=="":
203: temp[x]=hash[type][x]
204: return temp
205: else:
206: return hash[type]
207:
208: else:
209: return {}
210:
211: def getFieldList(self):
212: """erzeuge string aus fields"""
213: try:
214: return string.join(self.fieldList,",")
215: except:
216: return ""
217:
218: def getFields(self):
219: """ausgabe der Felder"""
220: return self.fieldList
221:
222: def getTypeTitle(self,id):
223: """Title von ID"""
224: try:
225: obj=getattr(self,id)
226: return obj.title
227: except:
228: return id
1.4 dwinter 229:
230: def getType(self,type):
231: """gib metadataobject type zurueck"""
232:
233: for obj in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping__neu']):
234: if obj[0]==type:
235: return obj
236: return (self.id,self)
237:
238:
1.1 dwinter 239:
240: def getStoredTypes(self):
241: """Gebe gespeicherte typen zurück"""
242:
243: types=[]
244:
245: for obj in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping_neu']):
246: if obj.title=="":
247: title=obj.id
248: else:
249: title=obj.title
1.4 dwinter 250: types.append((obj.id,title,obj))
1.1 dwinter 251:
252: return types
253:
254: def indicateDisplayFieldsForm(self):
255: """form zur Makierung der Felder die in der Browserumgebung angezeigt werden"""
256: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','indicateDisplayFieldsForm.zpt')).__of__(self)
257: return pt()
258:
259: def indicateDisplayFields(self,displayFields,RESPONSE=None):
260: """set Displayfields
261: @param displayFields: Liste von Felder die im Browserenvironment angezeigt werden
262: """
263: self.displayFields=OSAS_helpers.toList(displayFields)
264: if RESPONSE is not None:
265: RESPONSE.redirect('manage_main')
266:
1.3 dwinter 267: def getDisplayFieldsAsStr(self,indexMeta):
1.4 dwinter 268: ret=[]
1.9 ! dwinter 269: try:
1.6 dwinter 270: if indexMeta and not (indexMeta==""):
1.5 dwinter 271: dom=xml.dom.pulldom.parseString(indexMeta)
1.4 dwinter 272:
1.5 dwinter 273: for (event,node) in dom:
1.4 dwinter 274:
1.5 dwinter 275: if event == xml.dom.pulldom.START_ELEMENT and node.tagName=="bib":
276: dom.expandNode(node)
1.4 dwinter 277:
1.5 dwinter 278: try:
279: type=node.getAttribute('type')
280: mapping=getattr(self,type).generateMappingHash()
281: except:
282: type='generic'
283: mapping=getattr(self,type).generateMappingHash()
1.4 dwinter 284:
1.5 dwinter 285: for field in self.displayFields:
286: try:
287: ret.append(OSAS_helpers.getText(node.getElementsByTagName(mapping[field][0])[0].childNodes))
288: except:
289: """nothing"""
1.4 dwinter 290:
1.5 dwinter 291: return "; ".join(ret)
1.6 dwinter 292: else:
1.5 dwinter 293: return ""
1.9 ! dwinter 294: except:
! 295: return ""
1.4 dwinter 296: def getDisplayFieldsAsStrOLD(self,indexMeta):
1.1 dwinter 297: """Gebe display fields als string zurück
298: @param path: Pfad zum Object
299: """
300: ret=[]
301: try:
1.3 dwinter 302: dom=xml.dom.minidom.parseString(indexMeta)
1.1 dwinter 303: except:
1.3 dwinter 304: zLOG.LOG("OSAS_metadata (getDisplayFieldsAsStr)",zLOG.INFO,"Cannot parse: %s"%indexMeta)
1.1 dwinter 305: try:
306: bib = dom.getElementsByTagName("meta")[0].getElementsByTagName("bib")[0]
307: except:
308: return ""
309: try:
310: type=bib.getAttribute('type')
311: mapping=getattr(self,type).generateMappingHash()
312: except:
313: type='generic'
314: mapping=getattr(self,type).generateMappingHash()
315:
316: for field in self.displayFields:
317: try:
318: ret.append(OSAS_helpers.getText(bib.getElementsByTagName(mapping[field][0])[0].childNodes))
319: except:
320: """nothing"""
321:
322: return "; ".join(ret)
323:
324: security.declarePublic('changeMetadataForm')
325: def changeMetadataForm(self):
326: """Main configuration"""
327: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMetadata.zpt')).__of__(self)
328: return pt()
329:
330: security.declarePublic('changeMetadata')
1.4 dwinter 331: def changeMetadata(self,shortDescription,description,fields,RESPONSE=None):
1.1 dwinter 332: """Change Metadata"""
1.4 dwinter 333: self.shortDescription=shortDescription
1.1 dwinter 334: self.description=description
335: self.fieldList=fields.split(",")[0:]
336: if RESPONSE is not None:
337: RESPONSE.redirect('manage_main')
338:
339: security.declarePublic('index_html')
340:
341: def importXMLSchemaForm(self):
342: """form"""
343: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','importXMLSchemaForm.zpt')).__of__(self)
344: return pt()
345:
1.4 dwinter 346:
1.1 dwinter 347: def importXMLSchema(self,file,RESPONSE=None):
348: """import xmlschema, Metadatenschema wird eingelesen und entsprechende Metadatenmappings angelegt."""
349:
350: dom=xml.dom.minidom.parse(file)
351: sets=dom.getElementsByTagName('set')
352: #erster schritt: anlegen der fieldlist
353: for set in sets:
354: if set.getAttribute('name')=='generic':
355: list=[]
356: for entry in set.getElementsByTagName('entry'):
357: list.append(entry.getAttribute('genericName'))
358: self.fieldList=list[0:]
359:
360: #zweiter schritt: anlegen der mapping
361: for set in sets:
362: id=set.getAttribute('name').encode('utf-8')
363: list=[]
364: argList={}
365: for entry in set.getElementsByTagName('entry'):
366: genericName=entry.getAttribute('genericName')
367: tag=entry.getAttribute('tag')
368: label=entry.getAttribute('label')
369: description=OSAS_helpers.getText(entry.childNodes)
370: argList[genericName]=(tag,label,description)
371: self._setObject(id,OSAS_MetadataMapping(id,id,argList))
372: if RESPONSE:
373: RESPONSE.write("Wrote: %s"%id)
1.4 dwinter 374:
375:
376: def createMetadataFragment(self,type,path,prefix="",presets={}):
377: """fragment"""
378: self.REQUEST.SESSION['MDF_type']=type
379: self.REQUEST.SESSION['MDF_path']=path
380: self.REQUEST.SESSION['MDF_prefix']=prefix
381: self.REQUEST.SESSION['MDF_presets']=presets
382:
383: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm_fragment.zpt')).__of__(self)
384: return pt()
385:
386: def createMetadataForm(self,type="",path=""):
387: """createMetadataForm"""
388: self.REQUEST.SESSION['MDF_type']=type
389: self.REQUEST.SESSION['MDF_path']=path
390:
391:
392: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm_template.zpt')).__of__(self)
393: return pt()
394:
1.7 dwinter 395: def readMetadata(self,MDF_path,MDF_type,MDF_prefix="",MDF_xpathStart="", MDF_addPath=None,MDF_identifyFields=None,newdoc=None,actualNode=None):
396:
397: if type(MDF_path)==ListType:
398: MDF_path=MDF_path[0]
399:
400: indexFile=os.path.join(MDF_path,'index.meta')
401:
402: server=xmlrpclib.Server(self.serverUrl)
403:
404: documentStr=server.getFile(indexFile)
405:
406: if documentStr:
407: newdoc=xml.dom.minidom.parseString(documentStr)
408: dom=newdoc.documentElement
409: actualNode=dom
410: else:
411: return {}
412:
413: if self.containerTag=="":
414: containerTag="doc"
415: else:
416: containerTag=self.containerTag
417:
418: if MDF_xpathStart=="":
419: dom=newdoc.documentElement
420: actualNode=dom
421: else:
422: #try to find xpath
423: if MDF_identifyFields:
424: query=[]
425: for field in MDF_identifyFields.keys():
426:
427: query.append("""(%s="%s")"""%(field,MDF_identifyFields[field]))
428: querystr=" and ".join(query)
429: xpathStr=MDF_xpathStart+"[%s]"%querystr
430:
431: else:
432: xpathStr=MDF_xpathStart
433:
434:
1.8 dwinter 435: xpathNodes=Evaluate(xpathStr,actualNode)
1.7 dwinter 436:
437:
438: if len(xpathNodes)>0:
439: actualNode=xpathNodes[0]
440: else:
441: return {}
442:
443: ret={}
444: for node in actualNode.childNodes:
445: name=node.tagName
446: text=OSAS_helpers.getText(node.childNodes)
447: ret[name]=text
448:
449: return ret
450:
1.4 dwinter 451: def writeMetadata(self,MDF_path,MDF_type,form,MDF_prefix="",MDF_xpathStart="", MDF_addPath=None,MDF_identifyFields=None,newdoc=None,actualNode=None):
452: """writeMetadata"""
453: #MDF_path="/tmp/index.meta"
454: if type(MDF_path)==ListType:
455: MDF_path=MDF_path[0]
456:
1.7 dwinter 457:
1.4 dwinter 458: indexFile=os.path.join(MDF_path,'index.meta')
1.7 dwinter 459:
1.4 dwinter 460: server=xmlrpclib.Server(self.serverUrl)
461: if newdoc:
462: if not actualNode: actualNode=newdoc
463: dom=newdoc
464: else:
465: documentStr=server.getFile(indexFile)
1.5 dwinter 466:
1.4 dwinter 467: if documentStr:
1.5 dwinter 468:
1.4 dwinter 469: newdoc=xml.dom.minidom.parseString(documentStr)
470: dom=newdoc.documentElement
471: actualNode=dom
472:
473:
474: else:
1.5 dwinter 475:
1.4 dwinter 476: impl=xml.dom.minidom.getDOMImplementation()
477: newdoc=None
478:
479:
480: if self.containerTag=="":
481: containerTag="doc"
482: else:
483: containerTag=self.containerTag
484:
485: create=None
486: if MDF_xpathStart=="":
487: if not newdoc:
488: newdoc=impl.createDocument(None,containerTag,None)
489: dom=newdoc.documentElement
490: actualNode=dom
491: else:
492:
493: #try to find xpath
494: if MDF_identifyFields:
495: query=[]
496: for field in MDF_identifyFields:
497:
498: query.append("""(%s="%s")"""%(field,form[MDF_prefix+"MD_"+field]))
499: querystr=" and ".join(query)
500: xpathStr=MDF_xpathStart+"[%s]"%querystr
501:
502: else:
503: xpathStr=MDF_xpathStart
504:
1.5 dwinter 505:
1.8 dwinter 506: xpathNodes=Evaluate(xpathStr,actualNode)
1.4 dwinter 507:
508:
509:
510:
511: if len(xpathNodes)>0:
512: actualNode=xpathNodes[0]
513:
514: else:
515: #existiert nicht dann neue erzeugen
516:
1.8 dwinter 517: if len(Evaluate(MDF_xpathStart,dom))>0:
1.4 dwinter 518:
519: create=True
520:
521: splitted=MDF_xpathStart.split("/")
522: base=""
523: for element in splitted:
524:
525: if not (element=="") and not (element==containerTag):
526: base="/".join([base,element])
527:
528: if not newdoc:
529: newdoc=impl.createDocument(None,element,None)
530: actualNode=newdoc.documentElement
531: dom=actualNode
532: else:
533: changed=None
534:
535: if not (MDF_addPath==base):
536:
537:
538: for childNode in actualNode.childNodes:
539: if getattr(childNode,'tagName','')==element:
540: actualNode=childNode
541: changed=1
542:
543: if (os.path.normpath("/".join(["",containerTag,base]))==MDF_xpathStart) and create:
544: actualNode=actualNode.parentNode
545: changed=None
546:
547: if not changed:
548: namenode=newdoc.createElement(element)
549:
550: actualNode.appendChild(namenode)
551: actualNode=namenode
552:
553:
554:
555:
556: for name in self.REQUEST.form.keys():
557: length=len(MDF_prefix)
558: if MDF_type and not (MDF_type == ""):
559: actualNode.setAttribute("type",MDF_type)
560: if name[0:3+length]==MDF_prefix+"MD_":
561: tagName=name[3+length:]
562:
563: #CHECK if element exists
564: for childNode in actualNode.childNodes:
565: if getattr(childNode,'tagName','')==tagName:
566: actualNode.removeChild(childNode).unlink()
567:
568: namenode=newdoc.createElement(tagName)
569: namenodetext=newdoc.createTextNode(self.REQUEST.form[name])
570: namenode.appendChild(namenodetext)
571: actualNode.appendChild(namenode)
572:
573: ret=newdoc.toxml(encoding='utf-8')
574:
575: server.writeMetaDataFile(indexFile,ret)
576:
577:
578: return newdoc,actualNode
579:
580: def writeMetadataFile(self,MDF_path,MDF_type,MDF_xpathStart="",newdoc=None,actualNode=None):
581: """writeMetaFile"""
582:
583: return self.writeMetadata(MDF_path,MDF_type,self.REQUEST.form,MDF_xpathStart=MDF_xpathStart,newdoc=newdoc,actualNode=actualNode)
584:
1.1 dwinter 585:
1.4 dwinter 586: def isEmptyValue(self,fieldName):
587: """im generischen fall stets falsch"""
588: return 1
589:
590: def getValue(self,fieldName):
591: """im generischen fall gleich fieldname"""
592: return fieldName,fieldName,"","",""
593:
594: def getList(self,list):
595: """return list"""
596:
597: if list=="":
598: return None
599: listsplit=list.split("\n")
600: return listsplit
601:
602: def showHelp(self,refType,genericTag):
603: """helptext"""
604: for reference in self.ZopeFind(self):
605: if reference[1].title==refType:
606: text=getattr(reference[1],'md_'+genericTag)[2]
607: return text
608: return "NO EXPLANATION"
609:
610: def showHelpTag(self,url,reftype,item):
611: """gen javascript for showhelp"""
612: url2=url+'/showHelp?refType=%s&genericTag=%s'%(reftype,item)
613: ret="""javascript:wd=window.open(\'%s\',\'Help\',\'width=300,height=250\');void(\'\');wd.focus();"""%url2
614: return ret
615:
616:
1.1 dwinter 617: def manage_addMetadataForm(self):
618: """interface for adding the OSAS_add_Metadata"""
619: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm.zpt')).__of__(self)
620: return pt()
621:
1.4 dwinter 622: def manage_addMetadata(self,id,shortDescription,description,fields,RESPONSE=None):
1.1 dwinter 623: """add the OSAS_root"""
1.4 dwinter 624: newObj=OSAS_Metadata(id,shortDescription,description,fields)
1.1 dwinter 625: self.Destination()._setObject(id,newObj)
626: if RESPONSE is not None:
627: RESPONSE.redirect('manage_main')
628:
629:
630: InitializeClass(OSAS_Metadata)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>