File:  [Repository] / OSA_system2 / OSAS_metadata.py
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Thu Mar 3 20:41:00 2005 UTC (19 years, 3 months ago) by dwinter
Branches: MAIN
CVS tags: HEAD
major new version

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>