""" 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
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="""<set name="%s">"""%self.title
for fieldName in self.readFieldsFromParent():
entry=getattr(self,"md_"+fieldName)
if entry[2]=="": # no explanation of this field
ret+="""<entry genericName="%s" tag="%s" label="%s"/>"""%(fieldName,entry[0],entry[1])
else:
ret+="""<entry genericName="%s" tag="%s" label="%s">%s</entry>"""%(fieldName,entry[0],entry[1],entry[2])
ret+="</set>"
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="""<set name="%s">"""%"generic"
for field in self.fieldList:
ret+="""<entry genericName="%s"/>"""%field
ret+="</set>"
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+="""<metadataExport>"""
ret+="""<metadata name="%s">"""%self.getId()
ret+=self.showGenericXML()
for entry in self.ZopeFind(self,obj_metatypes=['OSAS_MetadataMapping__neu']):
ret+=entry[1].showSetXML()
for entry in self.ZopeFind(self,obj_metatypes=['OSAS_Metadata__neu']):
ret+=entry[1].showOverviewXML()
ret+="</metadata>"
if wrapped:
ret+="""</metadataExport>"""
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')
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>