changeset 84:a6e4f9b6729a

first version with new full-text infrastructure and slightly changed templates
author casties
date Fri, 19 Mar 2010 12:42:40 +0100
parents ec12a2440daa
children d3d7d05dfc54
files documentViewer.py
diffstat 1 files changed, 203 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/documentViewer.py	Mon Mar 08 16:02:33 2010 +0100
+++ b/documentViewer.py	Fri Mar 19 12:42:40 2010 +0100
@@ -12,6 +12,7 @@
 
 
 import Ft.Xml.XPath
+import cStringIO
 import xmlrpclib
 import os.path
 import sys
@@ -22,6 +23,7 @@
 
 import urlparse 
 from types import *
+
 def logger(txt,method,txt2):
     """logging"""
     logging.info(txt+ txt2)
@@ -45,6 +47,14 @@
            rc = rc + node.data
     return rc
 
+def serializeNode(node, encoding='utf-8'):
+    """returns a string containing node as XML"""
+    buf = cStringIO.StringIO()
+    Print(node, stream=buf, encoding=encoding)
+    s = buf.getvalue()
+    buf.close()
+    return s
+
         
 def getParentDir(path):
     """returns pathname shortened by one"""
@@ -78,7 +88,9 @@
     # templates and forms
     viewer_main = PageTemplateFile('zpt/viewer_main', globals())
     thumbs_main = PageTemplateFile('zpt/thumbs_main', globals())
-    image_main = PageTemplateFile('zpt/image_main', globals())
+    image_main = PageTemplateFile('zpt/image_main', globals()) # obsolete!
+    page_main_images = PageTemplateFile('zpt/page_main_images', globals())
+    page_main_text = PageTemplateFile('zpt/page_main_text', globals())
     head_main = PageTemplateFile('zpt/head_main', globals())
     docuviewer_css = PageTemplateFile('css/docuviewer.css', globals())
     info_xml = PageTemplateFile('zpt/info_xml', globals())
@@ -88,24 +100,34 @@
     changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
 
     
-    def __init__(self,id,imageViewerUrl,textViewerUrl=None,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=10,authgroups="mpiwg"):
+    def __init__(self,id,imageScalerUrl=None,textServerName=None,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=10,authgroups="mpiwg"):
         """init document viewer"""
         self.id=id
         self.title=title
-        self.imageViewerUrl=imageViewerUrl
-        self.textViewerUrl=textViewerUrl
-        
-        if not digilibBaseUrl:
-            self.digilibBaseUrl = self.findDigilibUrl()
-        else:
-            self.digilibBaseUrl = digilibBaseUrl
         self.thumbcols = thumbcols
         self.thumbrows = thumbrows
         # authgroups is list of authorized groups (delimited by ,)
         self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
-        # add template folder so we can always use template.something
-        self.manage_addFolder('template')
-
+        # create template folder so we can always use template.something
+        
+        templateFolder = Folder('template')
+        #self['template'] = templateFolder # Zope-2.12 style
+        self._setObject('template',templateFolder) # old style
+        try:
+            from Products.XMLRpcTools.XMLRpcTools import XMLRpcServerProxy
+            xmlRpcClient = XMLRpcServerProxy(id='fulltextclient', serverUrl=textServerName, use_xmlrpc=False)
+            #templateFolder['fulltextclient'] = xmlRpcClient
+            templateFolder._setObject('fulltextclient',xmlRpcClient)
+        except Exception, e:
+            logging.error("Unable to create XMLRpcTools for fulltextclient: "+str(e))
+        try:
+            from Products.zogiLib.zogiLib import zogiLib
+            zogilib = zogiLib(id="zogilib", title="zogilib for docuviewer", dlServerURL=imageScalerUrl, layout="book")
+            #templateFolder['zogilib'] = zogilib
+            templateFolder._setObject('zogilib',zogilib)
+        except Exception, e:
+            logging.error("Unable to create zogiLib for zogilib: "+str(e))
+        
 
     security.declareProtected('View','thumbs_rss')
     def thumbs_rss(self,mode,url,viewMode="auto",start=None,pn=1):
@@ -116,7 +138,7 @@
         @param viewMode: if images display images, if text display text, default is images (text,images or auto)
         
         '''
-        logging.info("HHHHHHHHHHHHHH:load the rss")
+        logging.debug("HHHHHHHHHHHHHH:load the rss")
         logger("documentViewer (index)", logging.INFO, "mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
         
         if not hasattr(self, 'template'):
@@ -139,7 +161,7 @@
         return pt(docinfo=docinfo,pageinfo=pageinfo,viewMode=viewMode)
   
     security.declareProtected('View','index_html')
-    def index_html(self,mode,url,viewMode="auto",start=None,pn=1,mk=None):
+    def index_html(self,url,mode="texttool",viewMode="auto",start=None,pn=1,mk=None):
         '''
         view it
         @param mode: defines how to access the document behind url 
@@ -148,13 +170,14 @@
         
         '''
         
-        logger("documentViewer (index)", logging.INFO, "mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
+        logging.debug("documentViewer (index) mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
         
         if not hasattr(self, 'template'):
-            # create template folder if it doesn't exist
-            self.manage_addFolder('template')
+            # this won't work
+            logging.error("template folder missing!")
+            return "ERROR: template folder missing!"
             
-        if not self.digilibBaseUrl:
+        if not getattr(self, 'digilibBaseUrl', None):
             self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
             
         docinfo = self.getDocinfo(mode=mode,url=url)
@@ -162,7 +185,7 @@
         pt = getattr(self.template, 'viewer_main')
         
         if viewMode=="auto": # automodus gewaehlt
-            if docinfo.get("textURL",'') and self.textViewerUrl: #texturl gesetzt und textViewer konfiguriert
+            if docinfo.get("textURL",''): #texturl gesetzt und textViewer konfiguriert
                 viewMode="text"
             else:
                 viewMode="images"
@@ -179,6 +202,19 @@
         for m in mk:
             ret+="mk=%s"%m
         return ret
+
+    def findDigilibUrl(self):
+        """try to get the digilib URL from zogilib"""
+        url = self.template.zogilib.getDLBaseUrl()
+        return url
+    
+    def getStyle(self, idx, selected, style=""):
+        """returns a string with the given style and append 'sel' if path == selected."""
+        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
+        if idx == selected:
+            return style + 'sel'
+        else:
+            return style
     
     def getLink(self,param=None,val=None):
         """link to documentviewer with parameter param set to val"""
@@ -189,7 +225,8 @@
                     del params[param]
             else:
                 params[param] = str(val)
-        if params["mode"] == "filepath": #wenn beim erst Aufruf filepath gesetzt wurde aendere das nun zu imagepath
+                
+        if params.get("mode", None) == "filepath": #wenn beim erst Aufruf filepath gesetzt wurde aendere das nun zu imagepath
                 params["mode"] = "imagepath"
                 params["url"] = getParentDir(params["url"])
                 
@@ -225,20 +262,6 @@
         return pt(docinfo=docinfo)
 
     
-    def getStyle(self, idx, selected, style=""):
-        """returns a string with the given style and append 'sel' if path == selected."""
-        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
-        if idx == selected:
-            return style + 'sel'
-        else:
-            return style
-
-    def getTextLanguage(self,url,docinfo):
-        docinfo['lang']=getTextFromNode(dom.xpath("//bib/lang")[0])
-        lang = urlencode({'':docinfo['lang']})
-        return lang
-        
-        
     def isAccessible(self, docinfo):
         """returns if access to the resource is granted"""
         access = docinfo.get('accessType', None)
@@ -291,6 +314,8 @@
             docinfo['numPages'] = int(getTextFromNode(sizes[0]))
         else:
             docinfo['numPages'] = 0
+            
+        # TODO: produce and keep list of image names and numbers
                         
         return docinfo
     
@@ -431,109 +456,106 @@
         return docinfo
     
     
-    def getNumPages(self, xquery, docinfo=None): #New Method 24.02.2010
-       text=self.viewerTemplates.query.eval("/mpdl/interface/xquery.xql","document="+ docinfo['textURLPath'] +"&xquery="+str(xquery))
-       docinfo['numPages'] = text.count("<pb ")
-       return docinfo
-       
+    def getDocinfoFromTextTool(self, url, dom=None, docinfo=None):
+        """parse texttool tag in index meta"""
+        logger("documentViewer (getdocinfofromtexttool)", logging.INFO, "url: %s" % (url))
+        if docinfo is None:
+           docinfo = {}
+            
+        if docinfo.get('lang', None) is None:
+            docinfo['lang'] = '' # default keine Sprache gesetzt
+        if dom is None:
+            dom = self.getIndexMeta(url)
+        
+        archivePath = None
+        archiveName = None
+    
+        archiveNames = dom.xpath("//resource/name")
+        if archiveNames and (len(archiveNames) > 0):
+            archiveName = getTextFromNode(archiveNames[0])
+        else:
+            logger("documentViewer (getdocinfofromtexttool)", logging.WARNING, "resource/name missing in: %s" % (url))
+        
+        archivePaths = dom.xpath("//resource/archive-path")
+        if archivePaths and (len(archivePaths) > 0):
+            archivePath = getTextFromNode(archivePaths[0])
+            # clean up archive path
+            if archivePath[0] != '/':
+                archivePath = '/' + archivePath
+            if archiveName and (not archivePath.endswith(archiveName)):
+                archivePath += "/" + archiveName
+        else:
+            # try to get archive-path from url
+            logger("documentViewer (getdocinfofromtexttool)", logging.WARNING, "resource/archive-path missing in: %s" % (url))
+            if (not url.startswith('http')):
+                archivePath = url.replace('index.meta', '')
+                
+        if archivePath is None:
+            # we balk without archive-path
+            raise IOError("Missing archive-path (for text-tool) in %s" % (url))
         
-    def getDocinfoFromTextTool(self,url,dom=None,docinfo=None):
-       """parse texttool tag in index meta"""
-       logger("documentViewer (getdocinfofromtexttool)", logging.INFO,"url: %s"%(url))
-       if docinfo is None:
-           docinfo = {}
-           
-       if docinfo.get('lang',None) is None:
-           docinfo['lang']='' # default keine Sprache gesetzt
-       if dom is None:
-           dom = self.getIndexMeta(url)
-       
-       archivePath = None
-       archiveName = None
+        imageDirs = dom.xpath("//texttool/image")
+        if imageDirs and (len(imageDirs) > 0):
+            imageDir = getTextFromNode(imageDirs[0])
+            
+        else:
+            # we balk with no image tag / not necessary anymore because textmode is now standard
+            #raise IOError("No text-tool info in %s"%(url))
+            imageDir = ""
+            #xquery="//pb"  
+            docinfo['imagePath'] = "" # keine Bilder
+            docinfo['imageURL'] = ""
+            
+        if imageDir and archivePath:
+            #print "image: ", imageDir, " archivepath: ", archivePath
+            imageDir = os.path.join(archivePath, imageDir)
+            imageDir = imageDir.replace("/mpiwg/online", '')
+            docinfo = self.getDirinfoFromDigilib(imageDir, docinfo=docinfo)
+            docinfo['imagePath'] = imageDir
+            
+            docinfo['imageURL'] = self.digilibBaseUrl + "/servlet/Scaler?fn=" + imageDir
+            
+        viewerUrls = dom.xpath("//texttool/digiliburlprefix")
+        if viewerUrls and (len(viewerUrls) > 0):
+            viewerUrl = getTextFromNode(viewerUrls[0])
+            docinfo['viewerURL'] = viewerUrl
+                   
+        textUrls = dom.xpath("//texttool/text")
+        if textUrls and (len(textUrls) > 0):
+            textUrl = getTextFromNode(textUrls[0])
+            if urlparse.urlparse(textUrl)[0] == "": #keine url
+                textUrl = os.path.join(archivePath, textUrl) 
+            # fix URLs starting with /mpiwg/online
+            if textUrl.startswith("/mpiwg/online"):
+                textUrl = textUrl.replace("/mpiwg/online", '', 1)
+            
+            docinfo['textURL'] = textUrl
+    
+        textUrls = dom.xpath("//texttool/text-url-path")
+        if textUrls and (len(textUrls) > 0):
+            textUrl = getTextFromNode(textUrls[0])
+            docinfo['textURLPath'] = textUrl   
+         
+        presentationUrls = dom.xpath("//texttool/presentation")
+        docinfo = self.getBibinfoFromIndexMeta(url, docinfo=docinfo, dom=dom)   # get info von bib tag
+        
+        if presentationUrls and (len(presentationUrls) > 0): # ueberschreibe diese durch presentation informationen 
+             # presentation url ergiebt sich ersetzen von index.meta in der url der fuer die Metadaten
+             # durch den relativen Pfad auf die presentation infos
+            presentationPath = getTextFromNode(presentationUrls[0])
+            if url.endswith("index.meta"): 
+                presentationUrl = url.replace('index.meta', presentationPath)
+            else:
+                presentationUrl = url + "/" + presentationPath
+            docinfo = self.getNumPages(docinfo) #im moment einfach auf eins setzen, navigation ueber die thumbs geht natuerlich nicht    
+            docinfo = self.getBibinfoFromTextToolPresentation(presentationUrl, docinfo=docinfo, dom=dom)
+    
+        docinfo = self.getAuthinfoFromIndexMeta(url, docinfo=docinfo, dom=dom)   # get access info
+        
+        return docinfo
 
-       archiveNames=dom.xpath("//resource/name")
-       if archiveNames and (len(archiveNames)>0):
-           archiveName=getTextFromNode(archiveNames[0])
-       else:
-           logger("documentViewer (getdocinfofromtexttool)", logging.WARNING,"resource/name missing in: %s"%(url))
-       
-       archivePaths=dom.xpath("//resource/archive-path")
-       if archivePaths and (len(archivePaths)>0):
-           archivePath=getTextFromNode(archivePaths[0])
-           # clean up archive path
-           if archivePath[0] != '/':
-               archivePath = '/' + archivePath
-           if archiveName and (not archivePath.endswith(archiveName)):
-               archivePath += "/" + archiveName
-       else:
-           # try to get archive-path from url
-           logger("documentViewer (getdocinfofromtexttool)", logging.WARNING,"resource/archive-path missing in: %s"%(url))
-           if (not url.startswith('http')):
-               archivePath = url.replace('index.meta', '')
-               
-       if archivePath is None:
-           # we balk without archive-path
-           raise IOError("Missing archive-path (for text-tool) in %s"%(url))
-       
-       imageDirs=dom.xpath("//texttool/image")
-       if imageDirs and (len(imageDirs)>0):
-           imageDir=getTextFromNode(imageDirs[0])
-           
-       else:
-           # we balk with no image tag / not necessary anymore because textmode is now standard
-           #raise IOError("No text-tool info in %s"%(url))
-           imageDir=""
-           #xquery="//pb"  
-           docinfo['imagePath'] = "" # keine Bilder
-           docinfo['imageURL'] = ""
-           
-       if imageDir and archivePath:
-           #print "image: ", imageDir, " archivepath: ", archivePath
-           imageDir=os.path.join(archivePath,imageDir)
-           imageDir=imageDir.replace("/mpiwg/online",'')
-           docinfo=self.getDirinfoFromDigilib(imageDir,docinfo=docinfo)
-           docinfo['imagePath'] = imageDir
-           
-           docinfo['imageURL'] = self.digilibBaseUrl+"/servlet/Scaler?fn="+imageDir
-           
-       viewerUrls=dom.xpath("//texttool/digiliburlprefix")
-       if viewerUrls and (len(viewerUrls)>0):
-           viewerUrl=getTextFromNode(viewerUrls[0])
-           docinfo['viewerURL'] = viewerUrl
-                  
-       textUrls=dom.xpath("//texttool/text")
-       if textUrls and (len(textUrls)>0):
-           textUrl=getTextFromNode(textUrls[0])
-           if urlparse.urlparse(textUrl)[0]=="": #keine url
-               textUrl=os.path.join(archivePath,textUrl) 
-           # fix URLs starting with /mpiwg/online
-           if textUrl.startswith("/mpiwg/online"):
-               textUrl = textUrl.replace("/mpiwg/online",'',1)
-           
-           docinfo['textURL'] = textUrl
-   
-       textUrls=dom.xpath("//texttool/text-url-path")
-       if textUrls and (len(textUrls)>0):
-           textUrl=getTextFromNode(textUrls[0])
-           docinfo['textURLPath'] = textUrl   
-        
-       presentationUrls=dom.xpath("//texttool/presentation")
-       docinfo = self.getBibinfoFromIndexMeta(url,docinfo=docinfo,dom=dom)   # get info von bib tag
-       
-       if presentationUrls and (len(presentationUrls)>0): # ueberschreibe diese durch presentation informationen 
-            # presentation url ergiebt sich ersetzen von index.meta in der url der fuer die Metadaten
-            # durch den relativen Pfad auf die presentation infos
-           presentationPath = getTextFromNode(presentationUrls[0])
-           if url.endswith("index.meta"): 
-               presentationUrl=url.replace('index.meta',presentationPath)
-           else:
-               presentationUrl=url + "/" + presentationPath
-           docinfo=self.getNumPages('//pb', docinfo) #im moment einfach auf eins setzen, navigation ueber die thumbs geht natuerlich nicht    
-           docinfo = self.getBibinfoFromTextToolPresentation(presentationUrl,docinfo=docinfo,dom=dom)
 
-       docinfo = self.getAuthinfoFromIndexMeta(url,docinfo=docinfo,dom=dom)   # get access info
-       
-       return docinfo
+
    
    
     def getBibinfoFromTextToolPresentation(self,url,docinfo=None,dom=None):
@@ -619,7 +641,6 @@
         pageinfo['start'] = start
         pageinfo['end'] = start + grpsize
         if docinfo is not None:
-            
             np = int(docinfo['numPages'])
             pageinfo['end'] = min(pageinfo['end'], np)
             pageinfo['numgroups'] = int(np / grpsize)
@@ -628,82 +649,57 @@
 
         return pageinfo
                 
-    def text(self,mode,url,pn):
-        """give text"""
-        if mode=="texttool": #index.meta with texttool information
-            (viewerUrl,imagepath,textpath)=parseUrlTextTool(url)
-        
-        #print textpath
-        try:
-            dom = NonvalidatingReader.parseUri(textpath)
-        except:
-            return None
-    
-        list=[]
-        nodes=dom.xpath("//pb")
+
 
-        node=nodes[int(pn)-1]
-        
-        p=node
-        
-        while p.tagName!="p":
-            p=p.parentNode
-        
-        
-        endNode=nodes[int(pn)]
-        
-        
-        e=endNode
-        
-        while e.tagName!="p":
-            e=e.parentNode
-        
-        
-        next=node.parentNode
+    def getNumPages(self,docinfo=None):
+        """get list of pages from fulltext and put in docinfo"""
+        xquery = '//pb'
+        text = self.template.fulltextclient.eval("/mpdl/interface/xquery.xql", "document=%s&xquery=%s"%(docinfo['textURLPath'],xquery))
+        # TODO: better processing of the page list. do we need the info somewhere else also?
+        docinfo['numPages'] = text.count("<pb ")
+        return docinfo
+       
+    def getTextPage(self, mode="text", pn=1, docinfo=None):
+        """returns single page from fulltext"""
+        pagexml=self.template.fulltextclient.eval("/mpdl/interface/page-fragment.xql", "document=%s&mode=%s&pn=%s"%(docinfo['textURLPath'],mode,pn), outputUnicode=False)
+        # post-processing downloaded xml
+        pagedom = Parse(pagexml)
+        # plain text mode
+        if mode == "text":
+            # first div contains text
+            pagedivs = pagedom.xpath("/div")
+            if len(pagedivs) > 0:
+                pagenode = pagedivs[0]
+                return serializeNode(pagenode)
+
+        # text-with-links mode
+        if mode == "textPollux":
+            # first div contains text
+            pagedivs = pagedom.xpath("/div")
+            if len(pagedivs) > 0:
+                pagenode = pagedivs[0]
+                # check all a-tags
+                links = pagenode.xpath("//a")
+                for l in links:
+                    hrefNode = l.getAttributeNodeNS(None, u"href")
+                    if hrefNode:
+                        # is link with href
+                        href = hrefNode.nodeValue
+                        if href.startswith('lt/lex.xql'):
+                            # is pollux link
+                            selfurl = self.absolute_url()
+                            # change href
+                            hrefNode.nodeValue = href.replace('lt/lex.xql','%s/head_main_voc'%selfurl)
+                            # add target
+                            l.setAttributeNS(None, 'target', '_blank')
+                return serializeNode(pagenode)
         
-        #sammle s
-        while next and (next!=endNode.parentNode):
-            list.append(next)    
-            next=next.nextSibling    
-        list.append(endNode.parentNode)
-        
-        if p==e:# beide im selben paragraphen
-            pass
-#    else:
-#            next=p
-#            while next!=e:
-#                print next,e
-#                list.append(next)
-#                next=next.nextSibling
-#            
-#        for x in list:
-#            PrettyPrint(x)
-#
-#        return list
-#
+        return "no text here"
 
-    def findDigilibUrl(self):
-        """try to get the digilib URL from zogilib"""
-        url = self.imageViewerUrl[:-1] + "/getScalerUrl"
-        #print urlparse.urlparse(url)[0]
-        #print urlparse.urljoin(self.absolute_url(),url)
-        logging.info("finddigiliburl: %s"%urlparse.urlparse(url)[0])
-        logging.info("finddigiliburl: %s"%urlparse.urljoin(self.absolute_url(),url))
-        
-        try:
-            if urlparse.urlparse(url)[0]=='': #relative path
-                url=urlparse.urljoin(self.absolute_url()+"/",url)
-                
-            scaler = urlopen(url).read()
-            return scaler.replace("/servlet/Scaler?", "")
-        except:
-            return None
     
-    def changeDocumentViewer(self,imageViewerUrl,textViewerUrl,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=10,authgroups='mpiwg',RESPONSE=None):
+    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=10,authgroups='mpiwg',RESPONSE=None):
         """init document viewer"""
         self.title=title
-        self.imageViewerUrl=imageViewerUrl
-        self.textViewerUrl=textViewerUrl
         self.digilibBaseUrl = digilibBaseUrl
         self.thumbrows = thumbrows
         self.thumbcols = thumbcols
@@ -713,17 +709,14 @@
     
     
         
-        
-#    security.declareProtected('View management screens','renameImageForm')
-
 def manage_AddDocumentViewerForm(self):
     """add the viewer form"""
     pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
     return pt()
   
-def manage_AddDocumentViewer(self,id,imageViewerUrl="",textViewerUrl="",title="",RESPONSE=None):
+def manage_AddDocumentViewer(self,id,imageScalerUrl="",textServerName="",title="",RESPONSE=None):
     """add the viewer"""
-    newObj=documentViewer(id,imageViewerUrl,title=title,textViewerUrl=textViewerUrl)
+    newObj=documentViewer(id,imageScalerUrl=imageScalerUrl,title=title,textServerName=textServerName)
     self._setObject(id,newObj)
     
     if RESPONSE is not None: