source: documentViewer/documentViewer.py @ 128:4db49915d825

Root_modularisierung
Last change on this file since 128:4db49915d825 was 128:4db49915d825, checked in by abukhman, 14 years ago

Last lemma

File size: 43.3 KB
Line 
1
2from OFS.Folder import Folder
3from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
4from Products.PageTemplates.PageTemplateFile import PageTemplateFile
5from Products.PythonScripts.standard import url_quote
6from AccessControl import ClassSecurityInfo
7from AccessControl import getSecurityManager
8from Globals import package_home
9
10from Ft.Xml.Domlette import NonvalidatingReader
11from Ft.Xml.Domlette import PrettyPrint, Print
12from Ft.Xml import EMPTY_NAMESPACE, Parse
13
14from xml.dom.minidom import parse, parseString
15
16
17
18import Ft.Xml.XPath
19import cStringIO
20import xmlrpclib
21import os.path
22import sys
23import cgi
24import urllib
25import logging
26import math
27
28import urlparse 
29from types import *
30
31def logger(txt,method,txt2):
32    """logging"""
33    logging.info(txt+ txt2)
34   
35   
36def getInt(number, default=0):
37    """returns always an int (0 in case of problems)"""
38    try:
39        return int(number)
40    except:
41        return int(default)
42
43def getTextFromNode(nodename):
44    """get the cdata content of a node"""
45    if nodename is None:
46        return ""
47    nodelist=nodename.childNodes
48    rc = ""
49    for node in nodelist:
50        if node.nodeType == node.TEXT_NODE:
51           rc = rc + node.data
52    return rc
53
54def serializeNode(node, encoding='utf-8'):
55    """returns a string containing node as XML"""
56    buf = cStringIO.StringIO()
57    Print(node, stream=buf, encoding=encoding)
58    s = buf.getvalue()
59    buf.close()
60    return s
61
62       
63def getParentDir(path):
64    """returns pathname shortened by one"""
65    return '/'.join(path.split('/')[0:-1])
66       
67
68import socket
69
70def urlopen(url,timeout=2):
71        """urlopen mit timeout"""
72        socket.setdefaulttimeout(timeout)
73        ret=urllib.urlopen(url)
74        socket.setdefaulttimeout(5)
75        return ret
76
77
78##
79## documentViewer class
80##
81class documentViewer(Folder):
82    """document viewer"""
83    #textViewerUrl="http://127.0.0.1:8080/HFQP/testXSLT/getPage?"
84   
85    meta_type="Document viewer"
86   
87    security=ClassSecurityInfo()
88    manage_options=Folder.manage_options+(
89        {'label':'main config','action':'changeDocumentViewerForm'},
90        )
91
92    # templates and forms
93    viewer_main = PageTemplateFile('zpt/viewer_main', globals())
94    toc_thumbs = PageTemplateFile('zpt/toc_thumbs', globals())
95    toc_text = PageTemplateFile('zpt/toc_text', globals())
96    toc_figures = PageTemplateFile('zpt/toc_figures', globals())
97    page_main_images = PageTemplateFile('zpt/page_main_images', globals())
98    page_main_text = PageTemplateFile('zpt/page_main_text', globals())
99    page_main_text_dict = PageTemplateFile('zpt/page_main_text_dict', globals())
100    page_main_xml = PageTemplateFile('zpt/page_main_xml', globals())
101    head_main = PageTemplateFile('zpt/head_main', globals())
102    docuviewer_css = PageTemplateFile('css/docuviewer.css', globals())
103    info_xml = PageTemplateFile('zpt/info_xml', globals())
104
105    thumbs_main_rss = PageTemplateFile('zpt/thumbs_main_rss', globals())
106    security.declareProtected('View management screens','changeDocumentViewerForm')   
107    changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
108
109   
110    def __init__(self,id,imageScalerUrl=None,textServerName=None,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=5,authgroups="mpiwg"):
111        """init document viewer"""
112        self.id=id
113        self.title=title
114        self.thumbcols = thumbcols
115        self.thumbrows = thumbrows
116        # authgroups is list of authorized groups (delimited by ,)
117        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
118        # create template folder so we can always use template.something
119       
120        templateFolder = Folder('template')
121        #self['template'] = templateFolder # Zope-2.12 style
122        self._setObject('template',templateFolder) # old style
123        try:
124            from Products.XMLRpcTools.XMLRpcTools import XMLRpcServerProxy
125            xmlRpcClient = XMLRpcServerProxy(id='fulltextclient', serverUrl=textServerName, use_xmlrpc=False)
126            #templateFolder['fulltextclient'] = xmlRpcClient
127            templateFolder._setObject('fulltextclient',xmlRpcClient)
128        except Exception, e:
129            logging.error("Unable to create XMLRpcTools for fulltextclient: "+str(e))
130        try:
131            from Products.zogiLib.zogiLib import zogiLib
132            zogilib = zogiLib(id="zogilib", title="zogilib for docuviewer", dlServerURL=imageScalerUrl, layout="book")
133            #templateFolder['zogilib'] = zogilib
134            templateFolder._setObject('zogilib',zogilib)
135        except Exception, e:
136            logging.error("Unable to create zogiLib for zogilib: "+str(e))
137       
138
139    security.declareProtected('View','thumbs_rss')
140    def thumbs_rss(self,mode,url,viewMode="auto",start=None,pn=1):
141        '''
142        view it
143        @param mode: defines how to access the document behind url
144        @param url: url which contains display information
145        @param viewMode: if images display images, if text display text, default is images (text,images or auto)
146       
147        '''
148        logging.debug("HHHHHHHHHHHHHH:load the rss")
149        logger("documentViewer (index)", logging.INFO, "mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
150       
151        if not hasattr(self, 'template'):
152            # create template folder if it doesn't exist
153            self.manage_addFolder('template')
154           
155        if not self.digilibBaseUrl:
156            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
157           
158        docinfo = self.getDocinfo(mode=mode,url=url)
159        pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo)
160        pt = getattr(self.template, 'thumbs_main_rss')
161       
162        if viewMode=="auto": # automodus gewaehlt
163            if docinfo.get("textURL",'') and self.textViewerUrl: #texturl gesetzt und textViewer konfiguriert
164                viewMode="text"
165            else:
166                viewMode="images"
167               
168        return pt(docinfo=docinfo,pageinfo=pageinfo,viewMode=viewMode)
169 
170    security.declareProtected('View','index_html')
171    def index_html(self,url,mode="texttool",viewMode="auto",tocMode="thumbs",start=None,pn=1,mk=None, query=None, querySearch=None):
172        '''
173        view it
174        @param mode: defines how to access the document behind url
175        @param url: url which contains display information
176        @param viewMode: if images display images, if text display text, default is auto (text,images or auto)
177        @param tocMode: type of 'table of contents' for navigation (thumbs, text, figures, none)
178        @param querySearch: type of different search modes (fulltext, fulltextMorph, xpath, xquery, ftIndex, ftIndexMorph, fulltextMorphLemma)
179        '''
180       
181        logging.debug("documentViewer (index) mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
182       
183        if not hasattr(self, 'template'):
184            # this won't work
185            logging.error("template folder missing!")
186            return "ERROR: template folder missing!"
187           
188        if not getattr(self, 'digilibBaseUrl', None):
189            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
190           
191        docinfo = self.getDocinfo(mode=mode,url=url)
192       
193       
194        if tocMode != "thumbs":
195            # get table of contents
196            docinfo = self.getToc(mode=tocMode, docinfo=docinfo)
197           
198        if viewMode=="auto": # automodus gewaehlt
199            if docinfo.get("textURL",''): #texturl gesetzt und textViewer konfiguriert
200                viewMode="text_dict"
201            else:
202                viewMode="images"
203               
204        pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo,viewMode=viewMode,tocMode=tocMode)
205       
206        pt = getattr(self.template, 'viewer_main')               
207        return pt(docinfo=docinfo,pageinfo=pageinfo,viewMode=viewMode,mk=self.generateMarks(mk))
208 
209    def generateMarks(self,mk):
210        ret=""
211        if mk is None:
212            return ""
213        if type(mk) is not ListType:
214                mk=[mk]
215        for m in mk:
216            ret+="mk=%s"%m
217        return ret
218
219
220    def findDigilibUrl(self):
221        """try to get the digilib URL from zogilib"""
222        url = self.template.zogilib.getDLBaseUrl()
223        return url
224
225    def getDocumentViewerURL(self):
226        """returns the URL of this instance"""
227        return self.absolute_url()
228   
229    def getStyle(self, idx, selected, style=""):
230        """returns a string with the given style and append 'sel' if path == selected."""
231        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
232        if idx == selected:
233            return style + 'sel'
234        else:
235            return style
236   
237    def getLink(self,param=None,val=None):
238        """link to documentviewer with parameter param set to val"""
239        params=self.REQUEST.form.copy()
240        if param is not None:
241            if val is None:
242                if params.has_key(param):
243                    del params[param]
244            else:
245                params[param] = str(val)
246               
247        if params.get("mode", None) == "filepath": #wenn beim erst Aufruf filepath gesetzt wurde aendere das nun zu imagepath
248                params["mode"] = "imagepath"
249                params["url"] = getParentDir(params["url"])
250               
251        # quote values and assemble into query string
252        ps = "&".join(["%s=%s"%(k,urllib.quote(v)) for (k, v) in params.items()])
253        url=self.REQUEST['URL1']+"?"+ps
254        return url
255
256    def getLinkAmp(self,param=None,val=None):
257        """link to documentviewer with parameter param set to val"""
258        params=self.REQUEST.form.copy()
259        if param is not None:
260            if val is None:
261                if params.has_key(param):
262                    del params[param]
263            else:
264                params[param] = str(val)
265               
266        # quote values and assemble into query string
267        logging.info("XYXXXXX: %s"%repr(params.items()))
268        ps = "&".join(["%s=%s"%(k,urllib.quote(v)) for (k, v) in params.items()])
269        url=self.REQUEST['URL1']+"?"+ps
270        return url
271   
272    def getInfo_xml(self,url,mode):
273        """returns info about the document as XML"""
274
275        if not self.digilibBaseUrl:
276            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
277       
278        docinfo = self.getDocinfo(mode=mode,url=url)
279        pt = getattr(self.template, 'info_xml')
280        return pt(docinfo=docinfo)
281
282   
283    def isAccessible(self, docinfo):
284        """returns if access to the resource is granted"""
285        access = docinfo.get('accessType', None)
286        logger("documentViewer (accessOK)", logging.INFO, "access type %s"%access)
287        if access is not None and access == 'free':
288            logger("documentViewer (accessOK)", logging.INFO, "access is free")
289            return True
290        elif access is None or access in self.authgroups:
291            # only local access -- only logged in users
292            user = getSecurityManager().getUser()
293            if user is not None:
294                #print "user: ", user
295                return (user.getUserName() != "Anonymous User")
296            else:
297                return False
298       
299        logger("documentViewer (accessOK)", logging.INFO, "unknown access type %s"%access)
300        return False
301   
302               
303    def getDirinfoFromDigilib(self,path,docinfo=None,cut=0):
304        """gibt param von dlInfo aus"""
305        num_retries = 3
306        if docinfo is None:
307            docinfo = {}
308       
309        for x in range(cut):
310               
311                path=getParentDir(path)
312       
313        infoUrl=self.digilibBaseUrl+"/dirInfo-xml.jsp?mo=dir&fn="+path
314   
315        logger("documentViewer (getparamfromdigilib)", logging.INFO, "dirInfo from %s"%(infoUrl))
316       
317        for cnt in range(num_retries):
318            try:
319                # dom = NonvalidatingReader.parseUri(imageUrl)
320                txt=urllib.urlopen(infoUrl).read()
321                dom = Parse(txt)
322                break
323            except:
324                logger("documentViewer (getdirinfofromdigilib)", logging.ERROR, "error reading %s (try %d)"%(infoUrl,cnt))
325        else:
326            raise IOError("Unable to get dir-info from %s"%(infoUrl))
327       
328        sizes=dom.xpath("//dir/size")
329        logger("documentViewer (getparamfromdigilib)", logging.INFO, "dirInfo:size"%sizes)
330       
331        if sizes:
332            docinfo['numPages'] = int(getTextFromNode(sizes[0]))
333        else:
334            docinfo['numPages'] = 0
335           
336        # TODO: produce and keep list of image names and numbers
337                       
338        return docinfo
339   
340           
341    def getIndexMeta(self, url):
342        """returns dom of index.meta document at url"""
343        num_retries = 3
344        dom = None
345        metaUrl = None
346        if url.startswith("http://"):
347            # real URL
348            metaUrl = url
349        else:
350            # online path
351            server=self.digilibBaseUrl+"/servlet/Texter?fn="
352            metaUrl=server+url.replace("/mpiwg/online","")
353            if not metaUrl.endswith("index.meta"):
354                metaUrl += "/index.meta"
355        logging.debug("METAURL: %s"%metaUrl)
356        for cnt in range(num_retries):
357            try:
358                # patch dirk encoding fehler treten dann nicht mehr auf
359                # dom = NonvalidatingReader.parseUri(metaUrl)
360                txt=urllib.urlopen(metaUrl).read()
361                dom = Parse(txt)
362                break
363            except:
364                logger("ERROR documentViewer (getIndexMeta)", logging.INFO,"%s (%s)"%sys.exc_info()[0:2])
365               
366        if dom is None:
367            raise IOError("Unable to read index meta from %s"%(url))
368                 
369        return dom
370   
371    def getPresentationInfoXML(self, url):
372        """returns dom of info.xml document at url"""
373        num_retries = 3
374        dom = None
375        metaUrl = None
376        if url.startswith("http://"):
377            # real URL
378            metaUrl = url
379        else:
380            # online path
381            server=self.digilibBaseUrl+"/servlet/Texter?fn="
382            metaUrl=server+url.replace("/mpiwg/online","")
383       
384        for cnt in range(num_retries):
385            try:
386                # patch dirk encoding fehler treten dann nicht mehr auf
387                # dom = NonvalidatingReader.parseUri(metaUrl)
388                txt=urllib.urlopen(metaUrl).read()
389                dom = Parse(txt)
390                break
391            except:
392                logger("ERROR documentViewer (getPresentationInfoXML)", logging.INFO,"%s (%s)"%sys.exc_info()[0:2])
393               
394        if dom is None:
395            raise IOError("Unable to read infoXMLfrom %s"%(url))
396                 
397        return dom
398                       
399       
400    def getAuthinfoFromIndexMeta(self,path,docinfo=None,dom=None,cut=0):
401        """gets authorization info from the index.meta file at path or given by dom"""
402        logger("documentViewer (getauthinfofromindexmeta)", logging.INFO,"path: %s"%(path))
403       
404        access = None
405       
406        if docinfo is None:
407            docinfo = {}
408           
409        if dom is None:
410            for x in range(cut):
411                path=getParentDir(path)
412            dom = self.getIndexMeta(path)
413       
414        acctype = dom.xpath("//access-conditions/access/@type")
415        if acctype and (len(acctype)>0):
416            access=acctype[0].value
417            if access in ['group', 'institution']:
418                access = getTextFromNode(dom.xpath("//access-conditions/access/name")[0]).lower()
419           
420        docinfo['accessType'] = access
421        return docinfo
422   
423       
424    def getBibinfoFromIndexMeta(self,path,docinfo=None,dom=None,cut=0):
425        """gets bibliographical info from the index.meta file at path or given by dom"""
426        logging.debug("documentViewer (getbibinfofromindexmeta) path: %s"%(path))
427       
428        if docinfo is None:
429            docinfo = {}
430       
431        if dom is None:
432            for x in range(cut):
433                path=getParentDir(path)
434            dom = self.getIndexMeta(path)
435       
436        logging.debug("documentViewer (getbibinfofromindexmeta cutted) path: %s"%(path))
437        # put in all raw bib fields as dict "bib"
438        bib = dom.xpath("//bib/*")
439        if bib and len(bib)>0:
440            bibinfo = {}
441            for e in bib:
442                bibinfo[e.localName] = getTextFromNode(e)
443            docinfo['bib'] = bibinfo
444       
445        # extract some fields (author, title, year) according to their mapping
446        metaData=self.metadata.main.meta.bib
447        bibtype=dom.xpath("//bib/@type")
448        if bibtype and (len(bibtype)>0):
449            bibtype=bibtype[0].value
450        else:
451            bibtype="generic"
452           
453        bibtype=bibtype.replace("-"," ") # wrong typesiin index meta "-" instead of " " (not wrong! ROC)
454        docinfo['bib_type'] = bibtype
455        bibmap=metaData.generateMappingForType(bibtype)
456        # if there is no mapping bibmap is empty (mapping sometimes has empty fields)
457        if len(bibmap) > 0 and len(bibmap['author'][0]) > 0:
458            try:
459                docinfo['author']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['author'][0])[0])
460            except: pass
461            try:
462                docinfo['title']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['title'][0])[0])
463            except: pass
464            try:
465                docinfo['year']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['year'][0])[0])
466            except: pass
467            logging.debug("documentViewer (getbibinfofromindexmeta) using mapping for %s"%bibtype)
468            try:
469                docinfo['lang']=getTextFromNode(dom.xpath("//bib/lang")[0])
470            except:
471                docinfo['lang']=''
472
473        return docinfo
474   
475   
476    def getDocinfoFromTextTool(self, url, dom=None, docinfo=None):
477        """parse texttool tag in index meta"""
478        logger("documentViewer (getdocinfofromtexttool)", logging.INFO, "url: %s" % (url))
479        if docinfo is None:
480           docinfo = {}
481        if docinfo.get('lang', None) is None:
482            docinfo['lang'] = '' # default keine Sprache gesetzt
483        if dom is None:
484            dom = self.getIndexMeta(url)
485       
486        archivePath = None
487        archiveName = None
488   
489        archiveNames = dom.xpath("//resource/name")
490        if archiveNames and (len(archiveNames) > 0):
491            archiveName = getTextFromNode(archiveNames[0])
492        else:
493            logger("documentViewer (getdocinfofromtexttool)", logging.WARNING, "resource/name missing in: %s" % (url))
494       
495        archivePaths = dom.xpath("//resource/archive-path")
496        if archivePaths and (len(archivePaths) > 0):
497            archivePath = getTextFromNode(archivePaths[0])
498            # clean up archive path
499            if archivePath[0] != '/':
500                archivePath = '/' + archivePath
501            if archiveName and (not archivePath.endswith(archiveName)):
502                archivePath += "/" + archiveName
503        else:
504            # try to get archive-path from url
505            logger("documentViewer (getdocinfofromtexttool)", logging.WARNING, "resource/archive-path missing in: %s" % (url))
506            if (not url.startswith('http')):
507                archivePath = url.replace('index.meta', '')
508               
509        if archivePath is None:
510            # we balk without archive-path
511            raise IOError("Missing archive-path (for text-tool) in %s" % (url))
512       
513        imageDirs = dom.xpath("//texttool/image")
514        if imageDirs and (len(imageDirs) > 0):
515            imageDir = getTextFromNode(imageDirs[0])
516           
517        else:
518            # we balk with no image tag / not necessary anymore because textmode is now standard
519            #raise IOError("No text-tool info in %s"%(url))
520            imageDir = ""
521            #xquery="//pb" 
522            docinfo['imagePath'] = "" # keine Bilder
523            docinfo['imageURL'] = ""
524           
525        if imageDir and archivePath:
526            #print "image: ", imageDir, " archivepath: ", archivePath
527            imageDir = os.path.join(archivePath, imageDir)
528            imageDir = imageDir.replace("/mpiwg/online", '')
529            docinfo = self.getDirinfoFromDigilib(imageDir, docinfo=docinfo)
530            docinfo['imagePath'] = imageDir
531           
532            docinfo['imageURL'] = self.digilibBaseUrl + "/servlet/Scaler?fn=" + imageDir
533           
534        viewerUrls = dom.xpath("//texttool/digiliburlprefix")
535        if viewerUrls and (len(viewerUrls) > 0):
536            viewerUrl = getTextFromNode(viewerUrls[0])
537            docinfo['viewerURL'] = viewerUrl
538                   
539        textUrls = dom.xpath("//texttool/text")
540        if textUrls and (len(textUrls) > 0):
541            textUrl = getTextFromNode(textUrls[0])
542            if urlparse.urlparse(textUrl)[0] == "": #keine url
543                textUrl = os.path.join(archivePath, textUrl) 
544            # fix URLs starting with /mpiwg/online
545            if textUrl.startswith("/mpiwg/online"):
546                textUrl = textUrl.replace("/mpiwg/online", '', 1)
547           
548            docinfo['textURL'] = textUrl
549   
550        textUrls = dom.xpath("//texttool/text-url-path")
551        if textUrls and (len(textUrls) > 0):
552            textUrl = getTextFromNode(textUrls[0])
553            docinfo['textURLPath'] = textUrl
554            if not docinfo['imagePath']:
555                # text-only, no page images
556                docinfo = self.getNumPages(docinfo) #im moment einfach auf eins setzen, navigation ueber die thumbs geht natuerlich nicht   
557         
558        presentationUrls = dom.xpath("//texttool/presentation")
559        docinfo = self.getBibinfoFromIndexMeta(url, docinfo=docinfo, dom=dom)   # get info von bib tag
560       
561        if presentationUrls and (len(presentationUrls) > 0): # ueberschreibe diese durch presentation informationen
562             # presentation url ergiebt sich ersetzen von index.meta in der url der fuer die Metadaten
563             # durch den relativen Pfad auf die presentation infos
564            presentationPath = getTextFromNode(presentationUrls[0])
565            if url.endswith("index.meta"): 
566                presentationUrl = url.replace('index.meta', presentationPath)
567            else:
568                presentationUrl = url + "/" + presentationPath
569               
570            docinfo = self.getBibinfoFromTextToolPresentation(presentationUrl, docinfo=docinfo, dom=dom)
571   
572        docinfo = self.getAuthinfoFromIndexMeta(url, docinfo=docinfo, dom=dom)   # get access info
573       
574        return docinfo
575   
576   
577    def getBibinfoFromTextToolPresentation(self,url,docinfo=None,dom=None):
578        """gets the bibliographical information from the preseantion entry in texttools
579        """
580        dom=self.getPresentationInfoXML(url)
581        try:
582            docinfo['author']=getTextFromNode(dom.xpath("//author")[0])
583        except:
584            pass
585        try:
586            docinfo['title']=getTextFromNode(dom.xpath("//title")[0])
587        except:
588            pass
589        try:
590            docinfo['year']=getTextFromNode(dom.xpath("//date")[0])
591        except:
592            pass
593        return docinfo
594   
595    def getDocinfoFromImagePath(self,path,docinfo=None,cut=0):
596        """path ist the path to the images it assumes that the index.meta file is one level higher."""
597        logger("documentViewer (getdocinfofromimagepath)", logging.INFO,"path: %s"%(path))
598        if docinfo is None:
599            docinfo = {}
600        path=path.replace("/mpiwg/online","")
601        docinfo['imagePath'] = path
602        docinfo=self.getDirinfoFromDigilib(path,docinfo=docinfo,cut=cut)
603       
604        pathorig=path
605        for x in range(cut):       
606                path=getParentDir(path)
607        logging.error("PATH:"+path)
608        imageUrl=self.digilibBaseUrl+"/servlet/Scaler?fn="+path
609        docinfo['imageURL'] = imageUrl
610       
611        #path ist the path to the images it assumes that the index.meta file is one level higher.
612        docinfo = self.getBibinfoFromIndexMeta(pathorig,docinfo=docinfo,cut=cut+1)
613        docinfo = self.getAuthinfoFromIndexMeta(pathorig,docinfo=docinfo,cut=cut+1)
614        return docinfo
615   
616   
617    def getDocinfo(self, mode, url):
618        """returns docinfo depending on mode"""
619        logger("documentViewer (getdocinfo)", logging.INFO,"mode: %s, url: %s"%(mode,url))
620        # look for cached docinfo in session
621        if self.REQUEST.SESSION.has_key('docinfo'):
622            docinfo = self.REQUEST.SESSION['docinfo']
623            # check if its still current
624            if docinfo is not None and docinfo.get('mode') == mode and docinfo.get('url') == url:
625                logger("documentViewer (getdocinfo)", logging.INFO,"docinfo in session: %s"%docinfo)
626                return docinfo
627        # new docinfo
628        docinfo = {'mode': mode, 'url': url}
629        if mode=="texttool": #index.meta with texttool information
630            docinfo = self.getDocinfoFromTextTool(url, docinfo=docinfo)
631        elif mode=="imagepath":
632            docinfo = self.getDocinfoFromImagePath(url, docinfo=docinfo)
633        elif mode=="filepath":
634            docinfo = self.getDocinfoFromImagePath(url, docinfo=docinfo,cut=1)
635        else:
636            logger("documentViewer (getdocinfo)", logging.ERROR,"unknown mode!")
637            raise ValueError("Unknown mode %s! Has to be one of 'texttool','imagepath','filepath'."%(mode))
638                       
639        logger("documentViewer (getdocinfo)", logging.INFO,"docinfo: %s"%docinfo)
640        self.REQUEST.SESSION['docinfo'] = docinfo
641        return docinfo
642               
643    def getPageinfo(self, current, start=None, rows=None, cols=None, docinfo=None, viewMode=None, tocMode=None):
644        """returns pageinfo with the given parameters"""
645        pageinfo = {}
646        current = getInt(current)
647        pageinfo['current'] = current
648        rows = int(rows or self.thumbrows)
649        pageinfo['rows'] = rows
650        cols = int(cols or self.thumbcols)
651        pageinfo['cols'] = cols
652        grpsize = cols * rows
653        pageinfo['groupsize'] = grpsize
654        start = getInt(start, default=(math.ceil(float(current)/float(grpsize))*grpsize-(grpsize-1)))
655        # int(current / grpsize) * grpsize +1))
656        pageinfo['start'] = start
657        pageinfo['end'] = start + grpsize
658        if (docinfo is not None) and ('numPages' in docinfo):
659            np = int(docinfo['numPages'])
660            pageinfo['end'] = min(pageinfo['end'], np)
661            pageinfo['numgroups'] = int(np / grpsize)
662            if np % grpsize > 0:
663                pageinfo['numgroups'] += 1       
664        pageinfo['viewMode'] = viewMode
665        pageinfo['tocMode'] = tocMode
666        pageinfo['query'] = self.REQUEST.get('query',' ')
667        pageinfo['queryType'] = self.REQUEST.get('queryType',' ')
668        pageinfo['querySearch'] =self.REQUEST.get('querySearch', 'fulltext')
669        pageinfo['textPN'] = self.REQUEST.get('textPN','1')
670        pageinfo['highlightQuery'] = self.REQUEST.get('highlightQuery','')
671        pageinfo['tocPageSize'] = self.REQUEST.get('tocPageSize', '30')
672        pageinfo['queryPageSize'] =self.REQUEST.get('queryPageSize', '10')
673        pageinfo['tocPN'] = self.REQUEST.get('tocPN', '1')
674        toc = int (pageinfo['tocPN'])
675        pageinfo['textPages'] =int (toc)
676       
677        if 'tocSize_%s'%tocMode in docinfo:
678            tocSize = int(docinfo['tocSize_%s'%tocMode])
679            tocPageSize = int(pageinfo['tocPageSize'])
680            # cached toc           
681            if tocSize%tocPageSize>0:
682                tocPages=tocSize/tocPageSize+1
683            else:
684                tocPages=tocSize/tocPageSize
685            pageinfo['tocPN'] = min (tocPages,toc)                   
686        pageinfo['searchPN'] =self.REQUEST.get('searchPN','1')
687        pageinfo['sn'] =self.REQUEST.get('sn','')
688        return pageinfo
689               
690    def getSearch(self, pn=1, pageinfo=None,  docinfo=None, query=None, queryType=None, lemma=None):
691        """get search list"""
692        docpath = docinfo['textURLPath'] 
693        url = docinfo['url']
694        logging.debug("documentViewer (gettoc) docpath: %s"%(docpath))
695        logging.debug("documentViewer (gettoc) url: %s"%(url))
696        pagesize = pageinfo['queryPageSize']
697        pn = pageinfo['searchPN']
698        sn = pageinfo['sn']
699        highlightQuery = pageinfo['highlightQuery']
700        query =pageinfo['query']
701        queryType =pageinfo['queryType']
702        viewMode=  pageinfo['viewMode']
703        tocMode = pageinfo['tocMode']
704        tocPN = pageinfo['tocPN']
705        selfurl = self.absolute_url()
706        page=self.template.fulltextclient.eval("/mpdl/interface/doc-query.xql","document=%s&mode=%s&queryType=%s&query=%s&queryResultPageSize=%s&queryResultPN=%s&sn=%s&viewMode=%s&highlightQuery=%s"%(docpath, 'text', queryType, query, pagesize, pn, sn, viewMode,highlightQuery) ,outputUnicode=False)               
707        pagexml = page.replace('?document=%s'%str(docpath),'?url=%s'%url)
708        pagedom = Parse(pagexml)
709        if (queryType=="fulltext")or(queryType=="xpath")or(queryType=="xquery")or(queryType=="fulltextMorphLemma"):   
710            pagedivs = pagedom.xpath("//div[@class='queryResultPage']")
711            if len(pagedivs)>0:
712                pagenode=pagedivs[0]
713                links=pagenode.xpath("//a")
714                for l in links:
715                    hrefNode = l.getAttributeNodeNS(None, u"href")
716                    if hrefNode:
717                        href = hrefNode.nodeValue
718                        if href.startswith('page-fragment.xql'):
719                            selfurl = self.absolute_url()           
720                            pagexml=href.replace('mode=text','mode=texttool&viewMode=%s&queryType=%s&query=%s&queryResultPageSize=%s&queryResultPN=%s&tocMode=%s&searchPN=%s&tocPN=%s'%(viewMode,queryType,query,pagesize,pn,tocMode,pn,tocPN))
721                            hrefNode.nodeValue = pagexml.replace('page-fragment.xql','%s'%selfurl)                                           
722                return serializeNode(pagenode)       
723        if (queryType=="fulltextMorph"):
724            pagedivs = pagedom.xpath("//div[@class='queryResult']")
725            if len(pagedivs)>0:
726                pagenode=pagedivs[0]
727                links=pagenode.xpath("//a")
728                for l in links:
729                    hrefNode = l.getAttributeNodeNS(None, u"href")
730                    if hrefNode:
731                        href = hrefNode.nodeValue
732                        if href.startswith('page-fragment.xql'):
733                            selfurl = self.absolute_url()       
734                            pagexml=href.replace('mode=text','mode=texttool&viewMode=%s&queryType=%s&query=%s&queryResultPageSize=%s&queryResultPN=%s&tocMode=%s&searchPN=%s&tocPN=%s'%(viewMode,queryType,query,pagesize,pn,tocMode,pn,tocPN))
735                            hrefNode.nodeValue = pagexml.replace('page-fragment.xql','%s'%selfurl) 
736                        if href.startswith('../lt/lemma.xql'):
737                            hrefNode.nodeValue = href.replace('../lt/lemma.xql','%s/template/head_main_lemma_New'%(selfurl))       
738                            l.setAttributeNS(None, 'target', '_blank')
739                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=400, scrollbars=1'); return false;")
740                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();') 
741                pagedivs = pagedom.xpath("//div[@class='queryResultMorphExpansion']")               
742                return serializeNode(pagenode)       
743        if (queryType=="ftIndex")or(queryType=="ftIndexMorph"):
744            pagedivs= pagedom.xpath("//div[@class='queryResultPage']")
745            if len(pagedivs)>0:
746                pagenode=pagedivs[0]
747                links=pagenode.xpath("//a")
748                for l in links:
749                    hrefNode = l.getAttributeNodeNS(None, u"href")
750                    if hrefNode:
751                        href = hrefNode.nodeValue
752                        hrefNode.nodeValue=href.replace('mode=text','mode=texttool&viewMode=%s&tocMode=%s&tocPN=%s&pn=%s'%(viewMode,tocMode,tocPN,pn))             
753                        if href.startswith('../lt/lex.xql'):
754                            hrefNode.nodeValue = href.replace('../lt/lex.xql','%s/template/head_main_voc'%selfurl)         
755                            l.setAttributeNS(None, 'target', '_blank')
756                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=400, scrollbars=1'); return false;")
757                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')
758                        if href.startswith('../lt/lemma.xql'):
759                            hrefNode.nodeValue = href.replace('../lt/lemma.xql','%s/template/head_main_lemma'%selfurl)       
760                            l.setAttributeNS(None, 'target', '_blank')
761                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=400, scrollbars=1'); return false;")
762                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')
763                return serializeNode(pagenode)     
764        return "no text here"   
765                       
766    def getNumPages(self,docinfo=None):
767        """get list of pages from fulltext and put in docinfo"""
768        xquery = '//pb'
769        text = self.template.fulltextclient.eval("/mpdl/interface/xquery.xql", "document=%s&xquery=%s"%(docinfo['textURLPath'],xquery))
770        # TODO: better processing of the page list. do we need the info somewhere else also?
771        docinfo['numPages'] = text.count("<pb ")
772        return docinfo
773       
774    def getTextPage(self, mode="text", pn=1, docinfo=None, pageinfo=None, highlightQuery=None,sn=None, viewMode=None, tocMode=None, tocPN=None):
775        """returns single page from fulltext"""
776        docpath = docinfo['textURLPath']
777        path = docinfo['textURLPath']
778        url = docinfo['url']
779        viewMode= pageinfo['viewMode']
780        tocMode = pageinfo['tocMode']
781        tocPN = pageinfo['tocPN']
782        selfurl = self.absolute_url()   
783        if mode == "text_dict":
784            textmode = "textPollux"
785        else:
786            textmode = mode
787       
788        textParam = "document=%s&mode=%s&pn=%s"%(docpath,textmode,pn)
789        if highlightQuery is not None:
790            textParam +="&highlightQuery=%s&sn=%s"%(highlightQuery,sn)           
791        pagexml=self.template.fulltextclient.eval("/mpdl/interface/page-fragment.xql", textParam, outputUnicode=False)
792        pagedom = Parse(pagexml)
793        # plain text mode
794        if mode == "text":
795            # first div contains text
796            pagedivs = pagedom.xpath("/div")
797            if len(pagedivs) > 0:     
798                pagenode = pagedivs[0]
799                links = pagenode.xpath("//a")
800                for l in links:
801                    hrefNode = l.getAttributeNodeNS(None, u"href")
802                    if hrefNode:
803                        href= hrefNode.nodeValue
804                        if href.startswith('#note-'):
805                            hrefNode.nodeValue = href.replace('#note-',"?url=%s&viewMode=%s&tocMode=%s&tocPN=%s&pn=%s#note-"%(url,viewMode,tocMode,tocPN,pn))
806                return serializeNode(pagenode)
807        if mode == "xml":
808              # first div contains text
809              pagedivs = pagedom.xpath("/div")
810              if len(pagedivs) > 0:
811                  pagenode = pagedivs[0]
812                  return serializeNode(pagenode)
813        if mode == "pureXml":
814              # first div contains text
815              pagedivs = pagedom.xpath("/div")
816              if len(pagedivs) > 0:
817                  pagenode = pagedivs[0]
818                  return serializeNode(pagenode)     
819        # text-with-links mode
820        if mode == "text_dict":
821            # first div contains text
822            pagedivs = pagedom.xpath("/div")
823            if len(pagedivs) > 0:
824                pagenode = pagedivs[0]
825                # check all a-tags
826                links = pagenode.xpath("//a")
827                for l in links:
828                    hrefNode = l.getAttributeNodeNS(None, u"href")
829                    if hrefNode:
830                        # is link with href
831                        href = hrefNode.nodeValue
832                        if href.startswith('lt/lex.xql'):
833                            # is pollux link
834                            selfurl = self.absolute_url()
835                            # change href
836                            hrefNode.nodeValue = href.replace('lt/lex.xql','%s/template/head_main_voc'%selfurl)
837                            # add target
838                            l.setAttributeNS(None, 'target', '_blank')
839                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=700, scrollbars=1'); return false;")
840                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')     
841                        if href.startswith('lt/lemma.xql'):   
842                            selfurl = self.absolute_url()
843                            hrefNode.nodeValue = href.replace('lt/lemma.xql','%s/template/head_main_lemma'%selfurl)
844                            l.setAttributeNS(None, 'target', '_blank')
845                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=700, scrollbars=1'); return false;")
846                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')   
847                        if href.startswith('#note-'):
848                            hrefNode.nodeValue = href.replace('#note-',"?url=%s&viewMode=%s&tocMode=%s&tocPN=%s&pn=%s#note-"%(url,viewMode,tocMode,tocPN,pn))   
849                return serializeNode(pagenode)
850        return "no text here"
851
852    def getTranslate(self, query=None, language=None):
853        """translate into another languages"""
854        pagexml=self.template.fulltextclient.eval("/mpdl/interface/lt/lex.xql","document=&language="+str(language)+"&query="+url_quote(str(query)))
855        return pagexml
856   
857    def getLemma(self, lemma=None, language=None):
858        """simular words lemma """
859        pagexml=self.template.fulltextclient.eval("/mpdl/interface/lt/lemma.xql","document=&language="+str(language)+"&lemma="+url_quote(str(lemma)))
860        return pagexml
861   
862    def getLemmaNew(self, query=None, language=None):
863        """simular words lemma """
864        pagexml=self.template.fulltextclient.eval("/mpdl/interface/lt/lemma.xql","document=&language="+str(language)+"&lemma="+url_quote(str(query)))
865        return pagexml
866
867    def getQuery (self,  docinfo=None, pageinfo=None, query=None, queryType=None, pn=1):
868         """number of"""
869         docpath = docinfo['textURLPath'] 
870         pagesize = pageinfo['queryPageSize']
871         pn = pageinfo['searchPN']
872         query =pageinfo['query']
873         queryType =pageinfo['queryType']
874         tocSearch = 0
875         tocDiv = None
876         pagexml=self.template.fulltextclient.eval("/mpdl/interface/doc-query.xql","document=%s&mode=%s&queryType=%s&query=%s&queryResultPageSize=%s&queryResultPN=%s"%(docpath, 'text', queryType, query, pagesize, pn) ,outputUnicode=False)
877         pagedom = Parse(pagexml)
878         numdivs = pagedom.xpath("//div[@class='queryResultHits']")
879         tocSearch = int(getTextFromNode(numdivs[0]))
880         tc=int((tocSearch/10)+1)
881         logging.debug("documentViewer (gettoc) tc: %s"%(tc))
882         return tc
883
884    def getToc(self, mode="text", docinfo=None):
885        """loads table of contents and stores in docinfo"""
886        logging.debug("documentViewer (gettoc) mode: %s"%(mode))
887        if mode == "none":
888            return docinfo       
889        if 'tocSize_%s'%mode in docinfo:
890            # cached toc
891            return docinfo
892       
893        docpath = docinfo['textURLPath']
894        # we need to set a result set size
895        pagesize = 1000
896        pn = 1
897        if mode == "text":
898            queryType = "toc"
899        else:
900            queryType = mode
901        # number of entries in toc
902        tocSize = 0
903        tocDiv = None
904        pagexml=self.template.fulltextclient.eval("/mpdl/interface/doc-query.xql", "document=%s&queryType=%s&queryResultPageSize=%s&queryResultPN=%s"%(docpath,queryType,pagesize,pn), outputUnicode=False)
905        # post-processing downloaded xml
906        pagedom = Parse(pagexml)
907        # get number of entries
908        numdivs = pagedom.xpath("//div[@class='queryResultHits']")
909        if len(numdivs) > 0:
910            tocSize = int(getTextFromNode(numdivs[0]))
911        docinfo['tocSize_%s'%mode] = tocSize
912        return docinfo
913   
914def getTocPage(self, mode="text", pn=1, pageinfo=None, docinfo=None):
915        """returns single page from the table of contents"""
916        # TODO: this should use the cached TOC
917        if mode == "text":
918            queryType = "toc"
919        else:
920            queryType = mode
921        docpath = docinfo['textURLPath']
922        path = docinfo['textURLPath']       
923        pagesize = pageinfo['tocPageSize']
924        pn = pageinfo['tocPN']
925        url = docinfo['url']
926        selfurl = self.absolute_url() 
927        viewMode=  pageinfo['viewMode']
928        tocMode = pageinfo['tocMode']
929        tocPN = pageinfo['tocPN']   
930        pagexml=self.template.fulltextclient.eval("/mpdl/interface/doc-query.xql", "document=%s&queryType=%s&queryResultPageSize=%s&queryResultPN=%s"%(docpath,queryType, pagesize, pn), outputUnicode=False)
931        page = pagexml.replace('page-fragment.xql?document=%s'%str(path),'%s?url=%s&viewMode=%s&tocMode=%s&tocPN=%s'%(selfurl,url, viewMode, tocMode, tocPN))
932        text = page.replace('mode=image','mode=texttool')
933        return text
934   
935def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',RESPONSE=None):
936        """init document viewer"""
937        self.title=title
938        self.digilibBaseUrl = digilibBaseUrl
939        self.thumbrows = thumbrows
940        self.thumbcols = thumbcols
941        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
942        if RESPONSE is not None:
943            RESPONSE.redirect('manage_main')
944       
945def manage_AddDocumentViewerForm(self):
946    """add the viewer form"""
947    pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
948    return pt()
949 
950def manage_AddDocumentViewer(self,id,imageScalerUrl="",textServerName="",title="",RESPONSE=None):
951    """add the viewer"""
952    newObj=documentViewer(id,imageScalerUrl=imageScalerUrl,title=title,textServerName=textServerName)
953    self._setObject(id,newObj)
954   
955    if RESPONSE is not None:
956        RESPONSE.redirect('manage_main')
957
958## DocumentViewerTemplate class
959class DocumentViewerTemplate(ZopePageTemplate):
960    """Template for document viewer"""
961    meta_type="DocumentViewer Template"
962
963
964def manage_addDocumentViewerTemplateForm(self):
965    """Form for adding"""
966    pt=PageTemplateFile('zpt/addDocumentViewerTemplate', globals()).__of__(self)
967    return pt()
968
969def manage_addDocumentViewerTemplate(self, id='viewer_main', title=None, text=None,
970                           REQUEST=None, submit=None):
971    "Add a Page Template with optional file content."
972
973    self._setObject(id, DocumentViewerTemplate(id))
974    ob = getattr(self, id)
975    txt=file(os.path.join(package_home(globals()),'zpt/viewer_main.zpt'),'r').read()
976    logging.info("txt %s:"%txt)
977    ob.pt_edit(txt,"text/html")
978    if title:
979        ob.pt_setTitle(title)
980    try:
981        u = self.DestinationURL()
982    except AttributeError:
983        u = REQUEST['URL1']
984       
985    u = "%s/%s" % (u, urllib.quote(id))
986    REQUEST.RESPONSE.redirect(u+'/manage_main')
987    return ''
988
989
990   
Note: See TracBrowser for help on using the repository browser.