""" Classes for managing metadata""" from OFS.SimpleItem import SimpleItem from Globals import InitializeClass,package_home from OFS.Folder import Folder from AccessControl import ClassSecurityInfo from Products.PageTemplates.PageTemplateFile import PageTemplateFile import os.path import sys import xml.dom.minidom import xml.dom.pulldom from Products.OSA_system2 import OSAS_helpers import logging #ersetzt logging def logger(txt,method,txt2): """logging""" logging.info(txt+ txt2) import string try: from xml.xpath import Evaluate except: from Ft.Xml.XPath import Evaluate import xmlrpclib from types import * class OSAS_MetadataMapping(SimpleItem): """Einfaches Mapping Object""" meta_type="OSAS_MetadataMapping__neu" def readFieldsFromParent(self): """read all elements from root""" return self.aq_parent.fieldList def __init__(self,id,title,arglist): """init @param id: id @param title: title fuer zope navigation @param arglist: dictionary mit Namen der zugelassenen generische Metadaten als key und Tripel als Werte (human readable, tag version,explanation """ self.id=id self.title=title for fieldName in arglist.keys(): setattr(self,"md_"+fieldName,arglist[fieldName]) manage_options = SimpleItem.manage_options+( {'label':'Main Config','action':'changeMetadataMappingForm'}, ) def showSetXML(self,RESPONSE=None): """prints out the mapping as XML""" ret=""""""%self.title for fieldName in self.readFieldsFromParent(): entry=getattr(self,"md_"+fieldName) if entry[2]=="": # no explanation of this field ret+=""""""%(fieldName,entry[0],entry[1]) else: ret+="""%s"""%(fieldName,entry[0],entry[1],entry[2]) ret+="" if not RESPONSE: return ret else: self.REQUEST.RESPONSE.setHeader('Content-Type','text/xml') return ret def getValue(self,fieldName): """get md value @param fieldName: Bezeichnung des gesuchten Metadatums @retunr: Value des Metadatums""" ret= getattr(self,"md_"+fieldName,(None,None,None,None,None)) if len(ret)!= 4: # alte MD haben keine info ueber optional/required und listen werte ret=ret+("","") return ret def isEmptyValue(self,fieldName): """teste ob fielname in diesem Metadatenschema definiert ist""" field=getattr(self,"md_"+fieldName,'') if field[1]=='': return 0 else: return 1 def generateMappingHash(self): """erzeugen des dictionaries: generisches Feld -> Definition in diesem Schema""" hash={} for field in self.fieldList: hash[field]=getattr(self,"md_"+field,'') return hash def changeMetadataMappingForm(self): """change""" pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMetadataMapping.zpt')).__of__(self) return pt() def changeMetadataMapping(self,titleOfObject,RESPONSE=None): """change""" self.title=titleOfObject arglist=self.REQUEST.form for fieldName in self.readFieldsFromParent(): setattr(self,"md_"+fieldName,(arglist[fieldName],arglist['label_'+fieldName],arglist['explanation_'+fieldName],arglist['status_'+fieldName],arglist['values_'+fieldName])) if RESPONSE is not None: RESPONSE.redirect('manage_main') manage_workspace=changeMetadataMappingForm def manage_addMetadataMappingForm(self): """interface for adding the OSAS_root""" pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataMappingForm.zpt')).__of__(self) return pt() def manage_addMetadataMapping(self,idOfObject,titleOfObject,RESPONSE=None): """add the OSAS_root""" argList={} for arg in self.fieldList: if not (arg in ['idOfObject','titleOfObject']): 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]) newObj=OSAS_MetadataMapping(idOfObject,titleOfObject,argList) self._setObject(idOfObject,newObj) if RESPONSE is not None: RESPONSE.redirect('manage_main') class OSAS_Metadata(Folder): """Foldertype enthaelt methoden zur Halbautomatischen Erstellung von Metadatenfiles""" security=ClassSecurityInfo() def __init__(self,id,shortDescription,description,fields): """initialize a new instance""" self.id = id self.shortDescription =shortDescription #label fuer link auf add page self.description=description #description of the method for link page self.fieldList=fields.split(",")[0:] meta_type='OSAS_Metadata__neu' manage_options = Folder.manage_options+( {'label':'Main Config','action':'changeMetadataForm'}, {'label':'Import XML Schema','action':'importXMLSchemaForm'}, {'label':'Select Fields for Display','action':'indicateDisplayFieldsForm'}, ) def showGenericXML(self,RESPONSE=None): """show generic fields as XML""" ret=""""""%"generic" for field in self.fieldList: ret+=""""""%field ret+="" if not RESPONSE: return ret else: self.REQUEST.RESPONSE.setHeader('Content-Type','text/xml') return ret def showOverviewXML(self,RESPONSE=None,wrapped=False): """gives an overview over the Metadata stored in this folder""" ret="" if wrapped: ret+="""""" ret+=""""""%self.getId() ret+=self.showGenericXML() for entry in self.ZopeFind(self,obj_metatypes=['MetadataMapping', 'OSAS_MetadataMapping__neu']): ret+=entry[1].showSetXML() for entry in self.ZopeFind(self,obj_metatypes=['MetaData','OSAS_Metadata__neu']): ret+=entry[1].showOverviewXML() ret+="" if wrapped: ret+="""""" if not RESPONSE: return ret else: RESPONSE.setHeader('Content-Type','text/xml') return ret def generateMappingList(self): """Erzeuge Mapping""" mapping={} for dict in self.__dict__: #print dict obj=getattr(self,dict) if hasattr(obj,'meta_type'): logging.debug("generateMappungList read type:"+repr(obj.meta_type)) if ((obj.meta_type=="OSAS_MetadataMapping__neu") or (obj.meta_type=="MetadataMapping")): #metadatamapping is the newer type logging.debug("generateMappungListadded:"+repr(obj.getId())) mapping[obj.getId()]=obj.generateMappingHash() return mapping def generateMappingForType(self,type,clean="yes"): """erzeuge spezifisches Mapping""" hash=self.generateMappingList() logging.debug("generateMappingForType:"+type) for key in hash.keys(): logging.debug("generateMappingForType comparing:"+key.lower()+type.lower()) if (key.lower() == type.lower()): if clean=="yes": temp={} for x in hash[key].keys(): if not hash[key][x]=="": temp[x]=hash[key][x] return temp else: return hash[key] return {} def getFieldList(self): """erzeuge string aus fields""" try: return string.join(self.fieldList,",") except: return "" security.declarePublic('getFields') def getFields(self): """ausgabe der Felder""" return self.fieldList def getTypeTitle(self,id): """Title von ID""" try: obj=getattr(self,id) return obj.title except: return id def getType(self,type): """gib metadataobject type zurueck""" for obj in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping__neu']): if obj[0]==type: return obj return (self.id,self) def getStoredTypes(self): """Gebe gespeicherte typen zurueck""" types=[] for obj in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping__neu']): if obj[1].title=="": title=obj[1].id else: title=obj[1].title types.append((obj[1].id, title, obj[1])) return types def indicateDisplayFieldsForm(self): """form zur Makierung der Felder die in der Browserumgebung angezeigt werden""" pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','indicateDisplayFieldsForm.zpt')).__of__(self) return pt() def indicateDisplayFields(self,displayFields,RESPONSE=None): """set Displayfields @param displayFields: Liste von Felder die im Browserenvironment angezeigt werden """ self.displayFields=OSAS_helpers.toList(displayFields) if RESPONSE is not None: RESPONSE.redirect('manage_main') def getDisplayFieldsAsStr(self,indexMeta): ret=[] try: if indexMeta and not (indexMeta==""): dom=xml.dom.pulldom.parseString(indexMeta) for (event,node) in dom: if event == xml.dom.pulldom.START_ELEMENT and node.tagName=="bib": dom.expandNode(node) try: type=node.getAttribute('type') mapping=getattr(self,type).generateMappingHash() except: type='generic' mapping=getattr(self,type).generateMappingHash() for field in self.displayFields: try: ret.append(OSAS_helpers.getText(node.getElementsByTagName(mapping[field][0])[0].childNodes)) except: """nothing""" return "; ".join(ret) else: return "" except: return "" def getDisplayFieldsAsStrOLD(self,indexMeta): """Gebe display fields als string zurueck @param path: Pfad zum Object """ ret=[] try: dom=xml.dom.minidom.parseString(indexMeta) except: logger("OSAS_metadata (getDisplayFieldsAsStr)",logging.INFO,"Cannot parse: %s"%indexMeta) try: bib = dom.getElementsByTagName("meta")[0].getElementsByTagName("bib")[0] except: return "" try: type=bib.getAttribute('type') mapping=getattr(self,type).generateMappingHash() except: type='generic' mapping=getattr(self,type).generateMappingHash() for field in self.displayFields: try: ret.append(OSAS_helpers.getText(bib.getElementsByTagName(mapping[field][0])[0].childNodes)) except: """nothing""" return "; ".join(ret) security.declarePublic('changeMetadataForm') def changeMetadataForm(self): """Main configuration""" pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMetadata.zpt')).__of__(self) return pt() security.declarePublic('changeMetadata') def changeMetadata(self,shortDescription,description,fields,RESPONSE=None): """Change Metadata""" self.shortDescription=shortDescription self.description=description self.fieldList=fields.split(",")[0:] if RESPONSE is not None: RESPONSE.redirect('manage_main') security.declarePublic('index_html') def importXMLSchemaForm(self): """form""" pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','importXMLSchemaForm.zpt')).__of__(self) return pt() def importXMLSchema(self,file,RESPONSE=None): """import xmlschema, Metadatenschema wird eingelesen und entsprechende Metadatenmappings angelegt.""" dom=xml.dom.minidom.parse(file) sets=dom.getElementsByTagName('set') #erster schritt: anlegen der fieldlist for set in sets: if set.getAttribute('name')=='generic': list=[] for entry in set.getElementsByTagName('entry'): list.append(entry.getAttribute('genericName')) self.fieldList=list[0:] #zweiter schritt: anlegen der mapping for set in sets: id=set.getAttribute('name').encode('utf-8') list=[] argList={} for entry in set.getElementsByTagName('entry'): genericName=entry.getAttribute('genericName') tag=entry.getAttribute('tag') label=entry.getAttribute('label') description=OSAS_helpers.getText(entry.childNodes) argList[genericName]=(tag,label,description) self._setObject(id,OSAS_MetadataMapping(id,id,argList)) if RESPONSE: RESPONSE.write("Wrote: %s"%id) def createMetadataFragment(self,type,path,prefix="",presets={}): """fragment""" self.REQUEST.SESSION['MDF_type']=type self.REQUEST.SESSION['MDF_path']=path self.REQUEST.SESSION['MDF_prefix']=prefix self.REQUEST.SESSION['MDF_presets']=presets pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm_fragment.zpt')).__of__(self) return pt() def createMetadataForm(self,type="",path=""): """createMetadataForm""" self.REQUEST.SESSION['MDF_type']=type self.REQUEST.SESSION['MDF_path']=path pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm_template.zpt')).__of__(self) return pt() def readMetadata(self,MDF_path,MDF_type,MDF_prefix="",MDF_xpathStart="", MDF_addPath=None,MDF_identifyFields=None,newdoc=None,actualNode=None): if type(MDF_path)==ListType: MDF_path=MDF_path[0] indexFile=os.path.join(MDF_path,'index.meta') server=xmlrpclib.Server(self.serverUrl) documentStr=server.getFile(indexFile) if documentStr: newdoc=xml.dom.minidom.parseString(documentStr) dom=newdoc.documentElement actualNode=dom else: return {} if self.containerTag=="": containerTag="doc" else: containerTag=self.containerTag if MDF_xpathStart=="": dom=newdoc.documentElement actualNode=dom else: #try to find xpath if MDF_identifyFields: query=[] for field in MDF_identifyFields.keys(): query.append("""(%s="%s")"""%(field,MDF_identifyFields[field])) querystr=" and ".join(query) xpathStr=MDF_xpathStart+"[%s]"%querystr else: xpathStr=MDF_xpathStart xpathNodes=Evaluate(xpathStr,actualNode) if len(xpathNodes)>0: actualNode=xpathNodes[0] else: return {} ret={} for node in actualNode.childNodes: name=node.tagName text=OSAS_helpers.getText(node.childNodes) ret[name]=text return ret def writeMetadata(self,MDF_path,MDF_type,form,MDF_prefix="",MDF_xpathStart="", MDF_addPath=None,MDF_identifyFields=None,newdoc=None,actualNode=None): """writeMetadata""" #MDF_path="/tmp/index.meta" if type(MDF_path)==ListType: MDF_path=MDF_path[0] indexFile=os.path.join(MDF_path,'index.meta') server=xmlrpclib.Server(self.serverUrl) if newdoc: if not actualNode: actualNode=newdoc dom=newdoc else: documentStr=server.getFile(indexFile) if documentStr: newdoc=xml.dom.minidom.parseString(documentStr) dom=newdoc.documentElement actualNode=dom else: impl=xml.dom.minidom.getDOMImplementation() newdoc=None if self.containerTag=="": containerTag="doc" else: containerTag=self.containerTag create=None if MDF_xpathStart=="": if not newdoc: newdoc=impl.createDocument(None,containerTag,None) dom=newdoc.documentElement actualNode=dom else: #try to find xpath if MDF_identifyFields: query=[] for field in MDF_identifyFields: query.append("""(%s="%s")"""%(field,form[MDF_prefix+"MD_"+field])) querystr=" and ".join(query) xpathStr=MDF_xpathStart+"[%s]"%querystr else: xpathStr=MDF_xpathStart xpathNodes=Evaluate(xpathStr,actualNode) if len(xpathNodes)>0: actualNode=xpathNodes[0] else: #existiert nicht dann neue erzeugen if len(Evaluate(MDF_xpathStart,dom))>0: create=True splitted=MDF_xpathStart.split("/") base="" for element in splitted: if not (element=="") and not (element==containerTag): base="/".join([base,element]) if not newdoc: newdoc=impl.createDocument(None,element,None) actualNode=newdoc.documentElement dom=actualNode else: changed=None if not (MDF_addPath==base): for childNode in actualNode.childNodes: if getattr(childNode,'tagName','')==element: actualNode=childNode changed=1 if (os.path.normpath("/".join(["",containerTag,base]))==MDF_xpathStart) and create: actualNode=actualNode.parentNode changed=None if not changed: namenode=newdoc.createElement(element) actualNode.appendChild(namenode) actualNode=namenode for name in self.REQUEST.form.keys(): length=len(MDF_prefix) if MDF_type and not (MDF_type == ""): actualNode.setAttribute("type",MDF_type) if name[0:3+length]==MDF_prefix+"MD_": tagName=name[3+length:] #CHECK if element exists for childNode in actualNode.childNodes: if getattr(childNode,'tagName','')==tagName: actualNode.removeChild(childNode).unlink() namenode=newdoc.createElement(tagName) namenodetext=newdoc.createTextNode(self.REQUEST.form[name]) namenode.appendChild(namenodetext) actualNode.appendChild(namenode) ret=newdoc.toxml(encoding='utf-8') zLOG.LOG("OSAS_metadata (writeMetadata)",zLOG.INFO,"write: %s"%ret) server.writeMetaDataFile(indexFile,ret) return newdoc,actualNode def writeMetadataFile(self,MDF_path,MDF_type,MDF_xpathStart="",newdoc=None,actualNode=None): """writeMetaFile""" return self.writeMetadata(MDF_path,MDF_type,self.REQUEST.form,MDF_xpathStart=MDF_xpathStart,newdoc=newdoc,actualNode=actualNode) def isEmptyValue(self,fieldName): """im generischen fall stets falsch""" return 1 def getValue(self,fieldName): """im generischen fall gleich fieldname""" return fieldName,fieldName,"","","" def getList(self,list): """return list""" if list=="": return None listsplit=[i.rstrip() for i in list.split("\n")] return listsplit def showHelp(self,refType,genericTag): """helptext""" for reference in self.ZopeFind(self): if reference[1].title==refType: text=getattr(reference[1],'md_'+genericTag)[2] return text return "NO EXPLANATION" def showHelpTag(self,url,reftype,item): """gen javascript for showhelp""" url2=url+'/showHelp?refType=%s&genericTag=%s'%(reftype,item) ret="""javascript:wd=window.open(\'%s\',\'Help\',\'width=300,height=250\');void(\'\');wd.focus();"""%url2 return ret def manage_addMetadataForm(self): """interface for adding the OSAS_add_Metadata""" pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMetadataForm.zpt')).__of__(self) return pt() def manage_addMetadata(self,id,shortDescription,description,fields,RESPONSE=None): """add the OSAS_root""" newObj=OSAS_Metadata(id,shortDescription,description,fields) self.Destination()._setObject(id,newObj) if RESPONSE is not None: RESPONSE.redirect('manage_main')