source: documentViewer/documentViewer.py @ 120:f1fc821f88a9

Last change on this file since 120:f1fc821f88a9 was 120:f1fc821f88a9, checked in by abukhman, 14 years ago

* empty log message *

File size: 43.6 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        pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo,viewMode=viewMode,tocMode=tocMode)
199       
200        if viewMode=="auto": # automodus gewaehlt
201            if docinfo.get("textURL",''): #texturl gesetzt und textViewer konfiguriert
202                viewMode="text"
203            else:
204                viewMode="images"
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 getStyle(self, idx, selected, style=""):
226        """returns a string with the given style and append 'sel' if path == selected."""
227        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
228        if idx == selected:
229            return style + 'sel'
230        else:
231            return style
232   
233    def getLink(self,param=None,val=None):
234        """link to documentviewer with parameter param set to val"""
235        params=self.REQUEST.form.copy()
236        if param is not None:
237            if val is None:
238                if params.has_key(param):
239                    del params[param]
240            else:
241                params[param] = str(val)
242               
243        if params.get("mode", None) == "filepath": #wenn beim erst Aufruf filepath gesetzt wurde aendere das nun zu imagepath
244                params["mode"] = "imagepath"
245                params["url"] = getParentDir(params["url"])
246               
247        # quote values and assemble into query string
248        ps = "&".join(["%s=%s"%(k,urllib.quote(v)) for (k, v) in params.items()])
249        url=self.REQUEST['URL1']+"?"+ps
250        return url
251
252    def getLinkAmp(self,param=None,val=None):
253        """link to documentviewer with parameter param set to val"""
254        params=self.REQUEST.form.copy()
255        if param is not None:
256            if val is None:
257                if params.has_key(param):
258                    del params[param]
259            else:
260                params[param] = str(val)
261               
262        # quote values and assemble into query string
263        logging.info("XYXXXXX: %s"%repr(params.items()))
264        ps = "&".join(["%s=%s"%(k,urllib.quote(v)) for (k, v) in params.items()])
265        url=self.REQUEST['URL1']+"?"+ps
266        return url
267   
268    def getInfo_xml(self,url,mode):
269        """returns info about the document as XML"""
270
271        if not self.digilibBaseUrl:
272            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
273       
274        docinfo = self.getDocinfo(mode=mode,url=url)
275        pt = getattr(self.template, 'info_xml')
276        return pt(docinfo=docinfo)
277
278   
279    def isAccessible(self, docinfo):
280        """returns if access to the resource is granted"""
281        access = docinfo.get('accessType', None)
282        logger("documentViewer (accessOK)", logging.INFO, "access type %s"%access)
283        if access is not None and access == 'free':
284            logger("documentViewer (accessOK)", logging.INFO, "access is free")
285            return True
286        elif access is None or access in self.authgroups:
287            # only local access -- only logged in users
288            user = getSecurityManager().getUser()
289            if user is not None:
290                #print "user: ", user
291                return (user.getUserName() != "Anonymous User")
292            else:
293                return False
294       
295        logger("documentViewer (accessOK)", logging.INFO, "unknown access type %s"%access)
296        return False
297   
298               
299    def getDirinfoFromDigilib(self,path,docinfo=None,cut=0):
300        """gibt param von dlInfo aus"""
301        num_retries = 3
302        if docinfo is None:
303            docinfo = {}
304       
305        for x in range(cut):
306               
307                path=getParentDir(path)
308       
309        infoUrl=self.digilibBaseUrl+"/dirInfo-xml.jsp?mo=dir&fn="+path
310   
311        logger("documentViewer (getparamfromdigilib)", logging.INFO, "dirInfo from %s"%(infoUrl))
312       
313        for cnt in range(num_retries):
314            try:
315                # dom = NonvalidatingReader.parseUri(imageUrl)
316                txt=urllib.urlopen(infoUrl).read()
317                dom = Parse(txt)
318                break
319            except:
320                logger("documentViewer (getdirinfofromdigilib)", logging.ERROR, "error reading %s (try %d)"%(infoUrl,cnt))
321        else:
322            raise IOError("Unable to get dir-info from %s"%(infoUrl))
323       
324        sizes=dom.xpath("//dir/size")
325        logger("documentViewer (getparamfromdigilib)", logging.INFO, "dirInfo:size"%sizes)
326       
327        if sizes:
328            docinfo['numPages'] = int(getTextFromNode(sizes[0]))
329        else:
330            docinfo['numPages'] = 0
331           
332        # TODO: produce and keep list of image names and numbers
333                       
334        return docinfo
335   
336           
337    def getIndexMeta(self, url):
338        """returns dom of index.meta document at url"""
339        num_retries = 3
340        dom = None
341        metaUrl = None
342        if url.startswith("http://"):
343            # real URL
344            metaUrl = url
345        else:
346            # online path
347            server=self.digilibBaseUrl+"/servlet/Texter?fn="
348            metaUrl=server+url.replace("/mpiwg/online","")
349            if not metaUrl.endswith("index.meta"):
350                metaUrl += "/index.meta"
351        logging.debug("METAURL: %s"%metaUrl)
352        for cnt in range(num_retries):
353            try:
354                # patch dirk encoding fehler treten dann nicht mehr auf
355                # dom = NonvalidatingReader.parseUri(metaUrl)
356                txt=urllib.urlopen(metaUrl).read()
357                dom = Parse(txt)
358                break
359            except:
360                logger("ERROR documentViewer (getIndexMeta)", logging.INFO,"%s (%s)"%sys.exc_info()[0:2])
361               
362        if dom is None:
363            raise IOError("Unable to read index meta from %s"%(url))
364                 
365        return dom
366   
367    def getPresentationInfoXML(self, url):
368        """returns dom of info.xml document at url"""
369        num_retries = 3
370        dom = None
371        metaUrl = None
372        if url.startswith("http://"):
373            # real URL
374            metaUrl = url
375        else:
376            # online path
377            server=self.digilibBaseUrl+"/servlet/Texter?fn="
378            metaUrl=server+url.replace("/mpiwg/online","")
379       
380        for cnt in range(num_retries):
381            try:
382                # patch dirk encoding fehler treten dann nicht mehr auf
383                # dom = NonvalidatingReader.parseUri(metaUrl)
384                txt=urllib.urlopen(metaUrl).read()
385                dom = Parse(txt)
386                break
387            except:
388                logger("ERROR documentViewer (getPresentationInfoXML)", logging.INFO,"%s (%s)"%sys.exc_info()[0:2])
389               
390        if dom is None:
391            raise IOError("Unable to read infoXMLfrom %s"%(url))
392                 
393        return dom
394                       
395       
396    def getAuthinfoFromIndexMeta(self,path,docinfo=None,dom=None,cut=0):
397        """gets authorization info from the index.meta file at path or given by dom"""
398        logger("documentViewer (getauthinfofromindexmeta)", logging.INFO,"path: %s"%(path))
399       
400        access = None
401       
402        if docinfo is None:
403            docinfo = {}
404           
405        if dom is None:
406            for x in range(cut):
407                path=getParentDir(path)
408            dom = self.getIndexMeta(path)
409       
410        acctype = dom.xpath("//access-conditions/access/@type")
411        if acctype and (len(acctype)>0):
412            access=acctype[0].value
413            if access in ['group', 'institution']:
414                access = getTextFromNode(dom.xpath("//access-conditions/access/name")[0]).lower()
415           
416        docinfo['accessType'] = access
417        return docinfo
418   
419       
420    def getBibinfoFromIndexMeta(self,path,docinfo=None,dom=None,cut=0):
421        """gets bibliographical info from the index.meta file at path or given by dom"""
422        logging.debug("documentViewer (getbibinfofromindexmeta) path: %s"%(path))
423       
424        if docinfo is None:
425            docinfo = {}
426       
427        if dom is None:
428            for x in range(cut):
429                path=getParentDir(path)
430            dom = self.getIndexMeta(path)
431       
432        logging.debug("documentViewer (getbibinfofromindexmeta cutted) path: %s"%(path))
433        # put in all raw bib fields as dict "bib"
434        bib = dom.xpath("//bib/*")
435        if bib and len(bib)>0:
436            bibinfo = {}
437            for e in bib:
438                bibinfo[e.localName] = getTextFromNode(e)
439            docinfo['bib'] = bibinfo
440       
441        # extract some fields (author, title, year) according to their mapping
442        metaData=self.metadata.main.meta.bib
443        bibtype=dom.xpath("//bib/@type")
444        if bibtype and (len(bibtype)>0):
445            bibtype=bibtype[0].value
446        else:
447            bibtype="generic"
448           
449        bibtype=bibtype.replace("-"," ") # wrong typesiin index meta "-" instead of " " (not wrong! ROC)
450        docinfo['bib_type'] = bibtype
451        bibmap=metaData.generateMappingForType(bibtype)
452        # if there is no mapping bibmap is empty (mapping sometimes has empty fields)
453        if len(bibmap) > 0 and len(bibmap['author'][0]) > 0:
454            try:
455                docinfo['author']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['author'][0])[0])
456            except: pass
457            try:
458                docinfo['title']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['title'][0])[0])
459            except: pass
460            try:
461                docinfo['year']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['year'][0])[0])
462            except: pass
463            logging.debug("documentViewer (getbibinfofromindexmeta) using mapping for %s"%bibtype)
464            try:
465                docinfo['lang']=getTextFromNode(dom.xpath("//bib/lang")[0])
466            except:
467                docinfo['lang']=''
468
469        return docinfo
470   
471   
472    def getDocinfoFromTextTool(self, url, dom=None, docinfo=None):
473        """parse texttool tag in index meta"""
474        logger("documentViewer (getdocinfofromtexttool)", logging.INFO, "url: %s" % (url))
475        if docinfo is None:
476           docinfo = {}
477        if docinfo.get('lang', None) is None:
478            docinfo['lang'] = '' # default keine Sprache gesetzt
479        if dom is None:
480            dom = self.getIndexMeta(url)
481       
482        archivePath = None
483        archiveName = None
484   
485        archiveNames = dom.xpath("//resource/name")
486        if archiveNames and (len(archiveNames) > 0):
487            archiveName = getTextFromNode(archiveNames[0])
488        else:
489            logger("documentViewer (getdocinfofromtexttool)", logging.WARNING, "resource/name missing in: %s" % (url))
490       
491        archivePaths = dom.xpath("//resource/archive-path")
492        if archivePaths and (len(archivePaths) > 0):
493            archivePath = getTextFromNode(archivePaths[0])
494            # clean up archive path
495            if archivePath[0] != '/':
496                archivePath = '/' + archivePath
497            if archiveName and (not archivePath.endswith(archiveName)):
498                archivePath += "/" + archiveName
499        else:
500            # try to get archive-path from url
501            logger("documentViewer (getdocinfofromtexttool)", logging.WARNING, "resource/archive-path missing in: %s" % (url))
502            if (not url.startswith('http')):
503                archivePath = url.replace('index.meta', '')
504               
505        if archivePath is None:
506            # we balk without archive-path
507            raise IOError("Missing archive-path (for text-tool) in %s" % (url))
508       
509        imageDirs = dom.xpath("//texttool/image")
510        if imageDirs and (len(imageDirs) > 0):
511            imageDir = getTextFromNode(imageDirs[0])
512           
513        else:
514            # we balk with no image tag / not necessary anymore because textmode is now standard
515            #raise IOError("No text-tool info in %s"%(url))
516            imageDir = ""
517            #xquery="//pb" 
518            docinfo['imagePath'] = "" # keine Bilder
519            docinfo['imageURL'] = ""
520           
521        if imageDir and archivePath:
522            #print "image: ", imageDir, " archivepath: ", archivePath
523            imageDir = os.path.join(archivePath, imageDir)
524            imageDir = imageDir.replace("/mpiwg/online", '')
525            docinfo = self.getDirinfoFromDigilib(imageDir, docinfo=docinfo)
526            docinfo['imagePath'] = imageDir
527           
528            docinfo['imageURL'] = self.digilibBaseUrl + "/servlet/Scaler?fn=" + imageDir
529           
530        viewerUrls = dom.xpath("//texttool/digiliburlprefix")
531        if viewerUrls and (len(viewerUrls) > 0):
532            viewerUrl = getTextFromNode(viewerUrls[0])
533            docinfo['viewerURL'] = viewerUrl
534                   
535        textUrls = dom.xpath("//texttool/text")
536        if textUrls and (len(textUrls) > 0):
537            textUrl = getTextFromNode(textUrls[0])
538            if urlparse.urlparse(textUrl)[0] == "": #keine url
539                textUrl = os.path.join(archivePath, textUrl) 
540            # fix URLs starting with /mpiwg/online
541            if textUrl.startswith("/mpiwg/online"):
542                textUrl = textUrl.replace("/mpiwg/online", '', 1)
543           
544            docinfo['textURL'] = textUrl
545   
546        textUrls = dom.xpath("//texttool/text-url-path")
547        if textUrls and (len(textUrls) > 0):
548            textUrl = getTextFromNode(textUrls[0])
549            docinfo['textURLPath'] = textUrl
550            if not docinfo['imagePath']:
551                # text-only, no page images
552                docinfo = self.getNumPages(docinfo) #im moment einfach auf eins setzen, navigation ueber die thumbs geht natuerlich nicht   
553         
554        presentationUrls = dom.xpath("//texttool/presentation")
555        docinfo = self.getBibinfoFromIndexMeta(url, docinfo=docinfo, dom=dom)   # get info von bib tag
556       
557        if presentationUrls and (len(presentationUrls) > 0): # ueberschreibe diese durch presentation informationen
558             # presentation url ergiebt sich ersetzen von index.meta in der url der fuer die Metadaten
559             # durch den relativen Pfad auf die presentation infos
560            presentationPath = getTextFromNode(presentationUrls[0])
561            if url.endswith("index.meta"): 
562                presentationUrl = url.replace('index.meta', presentationPath)
563            else:
564                presentationUrl = url + "/" + presentationPath
565               
566            docinfo = self.getBibinfoFromTextToolPresentation(presentationUrl, docinfo=docinfo, dom=dom)
567   
568        docinfo = self.getAuthinfoFromIndexMeta(url, docinfo=docinfo, dom=dom)   # get access info
569       
570        return docinfo
571   
572   
573    def getBibinfoFromTextToolPresentation(self,url,docinfo=None,dom=None):
574        """gets the bibliographical information from the preseantion entry in texttools
575        """
576        dom=self.getPresentationInfoXML(url)
577        try:
578            docinfo['author']=getTextFromNode(dom.xpath("//author")[0])
579        except:
580            pass
581        try:
582            docinfo['title']=getTextFromNode(dom.xpath("//title")[0])
583        except:
584            pass
585        try:
586            docinfo['year']=getTextFromNode(dom.xpath("//date")[0])
587        except:
588            pass
589        return docinfo
590   
591    def getDocinfoFromImagePath(self,path,docinfo=None,cut=0):
592        """path ist the path to the images it assumes that the index.meta file is one level higher."""
593        logger("documentViewer (getdocinfofromimagepath)", logging.INFO,"path: %s"%(path))
594        if docinfo is None:
595            docinfo = {}
596        path=path.replace("/mpiwg/online","")
597        docinfo['imagePath'] = path
598        docinfo=self.getDirinfoFromDigilib(path,docinfo=docinfo,cut=cut)
599       
600        pathorig=path
601        for x in range(cut):       
602                path=getParentDir(path)
603        logging.error("PATH:"+path)
604        imageUrl=self.digilibBaseUrl+"/servlet/Scaler?fn="+path
605        docinfo['imageURL'] = imageUrl
606       
607        #path ist the path to the images it assumes that the index.meta file is one level higher.
608        docinfo = self.getBibinfoFromIndexMeta(pathorig,docinfo=docinfo,cut=cut+1)
609        docinfo = self.getAuthinfoFromIndexMeta(pathorig,docinfo=docinfo,cut=cut+1)
610        return docinfo
611   
612   
613    def getDocinfo(self, mode, url):
614        """returns docinfo depending on mode"""
615        logger("documentViewer (getdocinfo)", logging.INFO,"mode: %s, url: %s"%(mode,url))
616        # look for cached docinfo in session
617        if self.REQUEST.SESSION.has_key('docinfo'):
618            docinfo = self.REQUEST.SESSION['docinfo']
619            # check if its still current
620            if docinfo is not None and docinfo.get('mode') == mode and docinfo.get('url') == url:
621                logger("documentViewer (getdocinfo)", logging.INFO,"docinfo in session: %s"%docinfo)
622                return docinfo
623        # new docinfo
624        docinfo = {'mode': mode, 'url': url}
625        if mode=="texttool": #index.meta with texttool information
626            docinfo = self.getDocinfoFromTextTool(url, docinfo=docinfo)
627        elif mode=="imagepath":
628            docinfo = self.getDocinfoFromImagePath(url, docinfo=docinfo)
629        elif mode=="filepath":
630            docinfo = self.getDocinfoFromImagePath(url, docinfo=docinfo,cut=1)
631        else:
632            logger("documentViewer (getdocinfo)", logging.ERROR,"unknown mode!")
633            raise ValueError("Unknown mode %s! Has to be one of 'texttool','imagepath','filepath'."%(mode))
634                       
635        logger("documentViewer (getdocinfo)", logging.INFO,"docinfo: %s"%docinfo)
636        self.REQUEST.SESSION['docinfo'] = docinfo
637        return docinfo
638       
639       
640    def getPageinfo(self, current, start=None, rows=None, cols=None, docinfo=None, viewMode=None, tocMode=None):
641        """returns pageinfo with the given parameters"""
642        pageinfo = {}
643        current = getInt(current)
644        pageinfo['current'] = current
645        rows = int(rows or self.thumbrows)
646        pageinfo['rows'] = rows
647        cols = int(cols or self.thumbcols)
648        pageinfo['cols'] = cols
649        grpsize = cols * rows
650        pageinfo['groupsize'] = grpsize
651        start = getInt(start, default=(math.ceil(float(current)/float(grpsize))*grpsize-(grpsize-1)))
652        # int(current / grpsize) * grpsize +1))
653        pageinfo['start'] = start
654        pageinfo['end'] = start + grpsize
655        if (docinfo is not None) and ('numPages' in docinfo):
656            np = int(docinfo['numPages'])
657            pageinfo['end'] = min(pageinfo['end'], np)
658            pageinfo['numgroups'] = int(np / grpsize)
659            if np % grpsize > 0:
660                pageinfo['numgroups'] += 1
661       
662         
663        pageinfo['viewMode'] = viewMode
664        pageinfo['tocMode'] = tocMode
665        pageinfo['query'] = self.REQUEST.get('query',' ')
666        pageinfo['queryType'] = self.REQUEST.get('queryType',' ')
667        pageinfo['querySearch'] =self.REQUEST.get('querySearch', 'fulltext')
668        pageinfo['textPN'] = self.REQUEST.get('textPN','1')
669        pageinfo['highlightQuery'] = self.REQUEST.get('highlightQuery','')
670        pageinfo['tocPageSize'] = self.REQUEST.get('tocPageSize', '30')
671        pageinfo['queryPageSize'] =self.REQUEST.get('queryPageSize', '10')
672        pageinfo['tocPN'] = self.REQUEST.get('tocPN', '1')
673        toc = int (pageinfo['tocPN'])
674        pageinfo['textPages'] =int (toc)
675       
676        if 'tocSize_%s'%tocMode in docinfo:
677            tocSize = int(docinfo['tocSize_%s'%tocMode])
678            tocPageSize = int(pageinfo['tocPageSize'])
679            # cached toc
680           
681            if tocSize%tocPageSize>0:
682                tocPages=tocSize/tocPageSize+1
683            else:
684                tocPages=tocSize/tocPageSize
685            pageinfo['tocPN'] = min (tocPages,toc)
686                     
687        pageinfo['searchPN'] =self.REQUEST.get('searchPN','1')
688        pageinfo['sn'] =self.REQUEST.get('sn','')
689
690        return pageinfo
691               
692    def getSearch(self, pn=1, pageinfo=None,  docinfo=None, query=None, queryType=None):
693        """get search list"""
694        docpath = docinfo['textURLPath'] 
695        url = docinfo['url']
696        logging.debug("documentViewer (gettoc) docpath: %s"%(docpath))
697        logging.debug("documentViewer (gettoc) url: %s"%(url))
698        pagesize = pageinfo['queryPageSize']
699        pn = pageinfo['searchPN']
700        sn = pageinfo['sn']
701        highlightQuery = pageinfo['highlightQuery']
702        query =pageinfo['query']
703        queryType =pageinfo['queryType']
704        viewMode=  pageinfo['viewMode']
705        tocMode = pageinfo['tocMode']
706        tocPN = pageinfo['tocPN']
707        selfurl = self.absolute_url()
708        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)               
709        pagexml = page.replace('?document=%s'%str(docpath),'?url=%s'%url)
710        pagedom = Parse(pagexml)
711        if (queryType=="fulltext")or(queryType=="xpath")or(queryType=="xquery")or(queryType=="fulltextMorphLemma"):   
712            pagedivs = pagedom.xpath("//div[@class='queryResultPage']")
713            if len(pagedivs)>0:
714                pagenode=pagedivs[0]
715                links=pagenode.xpath("//a")
716                for l in links:
717                    hrefNode = l.getAttributeNodeNS(None, u"href")
718                    if hrefNode:
719                        href = hrefNode.nodeValue
720                        if href.startswith('page-fragment.xql'):
721                            selfurl = self.absolute_url()           
722                            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))
723                            hrefNode.nodeValue = pagexml.replace('page-fragment.xql','%s'%selfurl)                                           
724                return serializeNode(pagenode)
725       
726        if (queryType=="fulltextMorph"):
727            pagedivs = pagedom.xpath("//div[@class='queryResult']")
728            if len(pagedivs)>0:
729                pagenode=pagedivs[0]
730                links=pagenode.xpath("//a")
731                for l in links:
732                    hrefNode = l.getAttributeNodeNS(None, u"href")
733                    if hrefNode:
734                        href = hrefNode.nodeValue
735                        if href.startswith('page-fragment.xql'):
736                            selfurl = self.absolute_url()       
737                            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))
738                            hrefNode.nodeValue = pagexml.replace('page-fragment.xql','%s'%selfurl) 
739                        if href.startswith('../lt/lemma.xql'):
740                           
741                            hrefNode.nodeValue = href.replace('../lt/lemma.xql','%s/template/head_main_lemma'%selfurl)       
742                            l.setAttributeNS(None, 'target', '_blank')
743                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=400, scrollbars=1'); return false;")
744                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();') 
745                pagedivs = pagedom.xpath("//div[@class='queryResultMorphExpansion']")               
746                return serializeNode(pagenode)
747       
748        if (queryType=="ftIndex")or(queryType=="ftIndexMorph"):
749            pagedivs= pagedom.xpath("//div[@class='queryResultPage']")
750            if len(pagedivs)>0:
751                pagenode=pagedivs[0]
752                links=pagenode.xpath("//a")
753                for l in links:
754                    hrefNode = l.getAttributeNodeNS(None, u"href")
755                    if hrefNode:
756                        href = hrefNode.nodeValue
757                        hrefNode.nodeValue=href.replace('mode=text','mode=texttool&viewMode=%s&tocMode=%s&tocPN=%s&pn=%s'%(viewMode,tocMode,tocPN,pn))
758                       
759                        if href.startswith('../lt/lex.xql'):
760                            hrefNode.nodeValue = href.replace('../lt/lex.xql','%s/template/head_main_voc'%selfurl)         
761                            l.setAttributeNS(None, 'target', '_blank')
762                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=400, scrollbars=1'); return false;")
763                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')
764                        if href.startswith('../lt/lemma.xql'):
765                            hrefNode.nodeValue = href.replace('../lt/lemma.xql','%s/template/head_main_lemma'%selfurl)       
766                            l.setAttributeNS(None, 'target', '_blank')
767                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=400, scrollbars=1'); return false;")
768                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')
769                return serializeNode(pagenode)     
770        return "no text here"   
771                       
772    def getNumPages(self,docinfo=None):
773        """get list of pages from fulltext and put in docinfo"""
774        xquery = '//pb'
775        text = self.template.fulltextclient.eval("/mpdl/interface/xquery.xql", "document=%s&xquery=%s"%(docinfo['textURLPath'],xquery))
776        # TODO: better processing of the page list. do we need the info somewhere else also?
777        docinfo['numPages'] = text.count("<pb ")
778        return docinfo
779       
780    def getTextPage(self, mode="text", pn=1, docinfo=None, pageinfo=None, highlightQuery=None,sn=None, viewMode=None, tocMode=None, tocPN=None):
781        """returns single page from fulltext"""
782        docpath = docinfo['textURLPath']
783        path = docinfo['textURLPath']
784        url = docinfo['url']
785        viewMode= pageinfo['viewMode']
786        tocMode = pageinfo['tocMode']
787        tocPN = pageinfo['tocPN']
788        selfurl = self.absolute_url()   
789       
790        #pn = pageinfo['searchPN']
791     
792        if mode == "text_dict":
793            textmode = "textPollux"
794        else:
795            textmode = mode
796       
797        textParam = "document=%s&mode=%s&pn=%s"%(docpath,textmode,pn)
798        if highlightQuery is not None:
799            textParam +="&highlightQuery=%s&sn=%s"%(highlightQuery,sn)
800           
801        pagexml=self.template.fulltextclient.eval("/mpdl/interface/page-fragment.xql", textParam, outputUnicode=False)
802        pagedom = Parse(pagexml)
803        # plain text mode
804        if mode == "text":
805            # first div contains text
806            pagedivs = pagedom.xpath("/div")
807            #queryResultPage
808            if len(pagedivs) > 0:     
809                pagenode = pagedivs[0]
810                links = pagenode.xpath("//a")
811                for l in links:
812                    hrefNode = l.getAttributeNodeNS(None, u"href")
813
814                    if hrefNode:
815                        href= hrefNode.nodeValue
816                        if href.startswith('#note-'):
817                            hrefNode.nodeValue = href.replace('#note-',"?url=%s&viewMode=%s&tocMode=%s&tocPN=%s&pn=%s#note-"%(url,viewMode,tocMode,tocPN,pn))
818               
819                return serializeNode(pagenode)
820        if mode == "xml":
821              # first div contains text
822              pagedivs = pagedom.xpath("/div")
823              if len(pagedivs) > 0:
824                  pagenode = pagedivs[0]
825                  return serializeNode(pagenode)
826        # text-with-links mode
827        if mode == "text_dict":
828            # first div contains text
829            pagedivs = pagedom.xpath("/div")
830            if len(pagedivs) > 0:
831                pagenode = pagedivs[0]
832                # check all a-tags
833                links = pagenode.xpath("//a")
834                for l in links:
835                    hrefNode = l.getAttributeNodeNS(None, u"href")
836                    if hrefNode:
837                        # is link with href
838                        href = hrefNode.nodeValue
839                        if href.startswith('lt/lex.xql'):
840                            # is pollux link
841                            selfurl = self.absolute_url()
842                            # change href
843                            hrefNode.nodeValue = href.replace('lt/lex.xql','%s/template/head_main_voc'%selfurl)
844                            # add target
845                            l.setAttributeNS(None, 'target', '_blank')
846                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=700, scrollbars=1'); return false;")
847                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')
848                           
849                        if href.startswith('lt/lemma.xql'):   
850                            selfurl = self.absolute_url()
851                            hrefNode.nodeValue = href.replace('lt/lemma.xql','%s/template/head_main_lemma'%selfurl)
852                            l.setAttributeNS(None, 'target', '_blank')
853                            l.setAttributeNS(None, 'onClick',"popupWin = window.open(this.href, 'contacts', 'location,width=500,height=600,top=180, left=700, scrollbars=1'); return false;")
854                            l.setAttributeNS(None, 'onDblclick', 'popupWin.focus();')
855                       
856                        if href.startswith('#note-'):
857                            hrefNode.nodeValue = href.replace('#note-',"?url=%s&viewMode=%s&tocMode=%s&tocPN=%s&pn=%s#note-"%(url,viewMode,tocMode,tocPN,pn))   
858                           
859                           
860                return serializeNode(pagenode)
861       
862        return "no text here"
863
864    def getTranslate(self, query=None, language=None):
865        """translate into another languages"""
866        pagexml=self.template.fulltextclient.eval("/mpdl/interface/lt/lex.xql","document=&language="+str(language)+"&query="+url_quote(str(query)))
867        return pagexml
868   
869    def getLemma(self, lemma=None, language=None):
870        """simular words lemma """
871        pagexml=self.template.fulltextclient.eval("/mpdl/interface/lt/lemma.xql","document=&language="+str(language)+"&lemma="+url_quote(str(lemma)))
872        #pagexml=self.template.fulltextclient.eval("/mpdl/interface/lt/lemma.xql","lemma=%s&language=%s"%(lemma,language),outputUnicode=False)
873        return pagexml
874
875    def getQuery (self,  docinfo=None, pageinfo=None, query=None, queryType=None, pn=1):
876         """number of"""
877         docpath = docinfo['textURLPath'] 
878         pagesize = pageinfo['queryPageSize']
879         pn = pageinfo['searchPN']
880         query =pageinfo['query']
881         queryType =pageinfo['queryType']
882
883         tocSearch = 0
884         tocDiv = None
885         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)
886         
887         pagedom = Parse(pagexml)
888         numdivs = pagedom.xpath("//div[@class='queryResultHits']")
889         tocSearch = int(getTextFromNode(numdivs[0]))
890         tc=int((tocSearch/10)+1)
891         logging.debug("documentViewer (gettoc) tc: %s"%(tc))
892         return tc
893
894    def getToc(self, mode="text", docinfo=None):
895        """loads table of contents and stores in docinfo"""
896        logging.debug("documentViewer (gettoc) mode: %s"%(mode))
897        if 'tocSize_%s'%mode in docinfo:
898            # cached toc
899            return docinfo
900        docpath = docinfo['textURLPath']
901        # we need to set a result set size
902        pagesize = 1000
903        pn = 1
904        if mode == "text":
905            queryType = "toc"
906        else:
907            queryType = mode
908        # number of entries in toc
909        tocSize = 0
910        tocDiv = None
911        pagexml=self.template.fulltextclient.eval("/mpdl/interface/doc-query.xql", "document=%s&queryType=%s&queryResultPageSize=%s&queryResultPN=%s"%(docpath,queryType,pagesize,pn), outputUnicode=False)
912        # post-processing downloaded xml
913        pagedom = Parse(pagexml)
914        # get number of entries
915        numdivs = pagedom.xpath("//div[@class='queryResultHits']")
916        if len(numdivs) > 0:
917            tocSize = int(getTextFromNode(numdivs[0]))
918            # div contains text
919            #pagedivs = pagedom.xpath("//div[@class='queryResultPage']")
920            #if len(pagedivs) > 0:
921            #    tocDiv = pagedivs[0]
922
923        docinfo['tocSize_%s'%mode] = tocSize
924        #docinfo['tocDiv_%s'%mode] = tocDiv
925        return docinfo
926   
927    def getTocPage(self, mode="text", pn=1, pageinfo=None, docinfo=None):
928        """returns single page from the table of contents"""
929        # TODO: this should use the cached TOC
930        if mode == "text":
931            queryType = "toc"
932        else:
933            queryType = mode
934        docpath = docinfo['textURLPath']
935        path = docinfo['textURLPath']
936        #logging.debug("documentViewer (gettoc) pathNomer: %s"%(pathNomer))
937        pagesize = pageinfo['tocPageSize']
938        pn = pageinfo['tocPN']
939        url = docinfo['url']
940        selfurl = self.absolute_url() 
941        viewMode=  pageinfo['viewMode']
942        tocMode = pageinfo['tocMode']
943        tocPN = pageinfo['tocPN']
944   
945        pagexml=self.template.fulltextclient.eval("/mpdl/interface/doc-query.xql", "document=%s&queryType=%s&queryResultPageSize=%s&queryResultPN=%s"%(docpath,queryType, pagesize, pn), outputUnicode=False)
946        page = pagexml.replace('page-fragment.xql?document=%s'%str(path),'%s?url=%s&viewMode=%s&tocMode=%s&tocPN=%s'%(selfurl,url, viewMode, tocMode, tocPN))
947        text = page.replace('mode=image','mode=texttool')
948        return text
949        # post-processing downloaded xml
950        #pagedom = Parse(text)
951        # div contains text
952        #pagedivs = pagedom.xpath("//div[@class='queryResultPage']")
953        #if len(pagedivs) > 0:
954        #    pagenode = pagedivs[0]
955        #    return serializeNode(pagenode)
956        #else:
957        #    return "No TOC!"
958
959   
960    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',RESPONSE=None):
961        """init document viewer"""
962        self.title=title
963        self.digilibBaseUrl = digilibBaseUrl
964        self.thumbrows = thumbrows
965        self.thumbcols = thumbcols
966        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
967        if RESPONSE is not None:
968            RESPONSE.redirect('manage_main')
969   
970   
971       
972def manage_AddDocumentViewerForm(self):
973    """add the viewer form"""
974    pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
975    return pt()
976 
977def manage_AddDocumentViewer(self,id,imageScalerUrl="",textServerName="",title="",RESPONSE=None):
978    """add the viewer"""
979    newObj=documentViewer(id,imageScalerUrl=imageScalerUrl,title=title,textServerName=textServerName)
980    self._setObject(id,newObj)
981   
982    if RESPONSE is not None:
983        RESPONSE.redirect('manage_main')
984
985
986##
987## DocumentViewerTemplate class
988##
989class DocumentViewerTemplate(ZopePageTemplate):
990    """Template for document viewer"""
991    meta_type="DocumentViewer Template"
992
993
994def manage_addDocumentViewerTemplateForm(self):
995    """Form for adding"""
996    pt=PageTemplateFile('zpt/addDocumentViewerTemplate', globals()).__of__(self)
997    return pt()
998
999def manage_addDocumentViewerTemplate(self, id='viewer_main', title=None, text=None,
1000                           REQUEST=None, submit=None):
1001    "Add a Page Template with optional file content."
1002
1003    self._setObject(id, DocumentViewerTemplate(id))
1004    ob = getattr(self, id)
1005    txt=file(os.path.join(package_home(globals()),'zpt/viewer_main.zpt'),'r').read()
1006    logging.info("txt %s:"%txt)
1007    ob.pt_edit(txt,"text/html")
1008    if title:
1009        ob.pt_setTitle(title)
1010    try:
1011        u = self.DestinationURL()
1012    except AttributeError:
1013        u = REQUEST['URL1']
1014       
1015    u = "%s/%s" % (u, urllib.quote(id))
1016    REQUEST.RESPONSE.redirect(u+'/manage_main')
1017    return ''
1018
1019
1020   
Note: See TracBrowser for help on using the repository browser.