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