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