source: documentViewer/documentViewer.py @ 486:f2c5417b7ff4

elementtree
Last change on this file since 486:f2c5417b7ff4 was 486:f2c5417b7ff4, checked in by casties, 13 years ago

more new template stuff

File size: 34.5 KB
Line 
1from OFS.Folder import Folder
2from OFS.Image import File
3from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
4from Products.PageTemplates.PageTemplateFile import PageTemplateFile
5from Products.ZSimpleFile import ZSimpleFile
6from AccessControl import ClassSecurityInfo
7from AccessControl import getSecurityManager
8from Globals import package_home
9
10#from Ft.Xml import EMPTY_NAMESPACE, Parse
11#import Ft.Xml.Domlette
12
13import xml.etree.ElementTree as ET
14
15import os.path
16import sys
17import urllib
18import logging
19import math
20import urlparse 
21import re
22import string
23
24from SrvTxtUtils import getInt, getText, getHttpData
25
26def logger(txt,method,txt2):
27    """logging"""
28    logging.info(txt+ txt2)
29   
30   
31def serializeNode(node, encoding="utf-8"):
32    """returns a string containing node as XML"""
33    s = ET.tostring(node)
34   
35    # 4Suite:
36    #    stream = cStringIO.StringIO()
37    #    Ft.Xml.Domlette.Print(node, stream=stream, encoding=encoding)
38    #    s = stream.getvalue()
39    #    stream.close()
40    return s
41
42def browserCheck(self):
43    """check the browsers request to find out the browser type"""
44    bt = {}
45    ua = self.REQUEST.get_header("HTTP_USER_AGENT")
46    bt['ua'] = ua
47    bt['isIE'] = False
48    bt['isN4'] = False
49    bt['versFirefox']=""
50    bt['versIE']=""
51    bt['versSafariChrome']=""
52    bt['versOpera']=""
53   
54    if string.find(ua, 'MSIE') > -1:
55        bt['isIE'] = True
56    else:
57        bt['isN4'] = (string.find(ua, 'Mozilla/4.') > -1)
58    # Safari oder Chrome identification   
59    try:
60        nav = ua[string.find(ua, '('):]
61        nav1=ua[string.find(ua,')'):]
62        nav2=nav1[string.find(nav1,'('):]
63        nav3=nav2[string.find(nav2,')'):]
64        ie = string.split(nav, "; ")[1]
65        ie1 =string.split(nav1, " ")[2]
66        ie2 =string.split(nav3, " ")[1]
67        ie3 =string.split(nav3, " ")[2]
68        if string.find(ie3, "Safari") >-1:
69            bt['versSafariChrome']=string.split(ie2, "/")[1]
70    except: pass
71    # IE identification
72    try:
73        nav = ua[string.find(ua, '('):]
74        ie = string.split(nav, "; ")[1]
75        if string.find(ie, "MSIE") > -1:
76            bt['versIE'] = string.split(ie, " ")[1]
77    except:pass
78    # Firefox identification
79    try:
80        nav = ua[string.find(ua, '('):]
81        nav1=ua[string.find(ua,')'):]
82        if string.find(ie1, "Firefox") >-1:
83            nav5= string.split(ie1, "/")[1]
84            logging.debug("FIREFOX: %s"%(nav5))
85            bt['versFirefox']=nav5[0:3]                   
86    except:pass
87    #Opera identification
88    try:
89        if string.find(ua,"Opera") >-1:
90            nav = ua[string.find(ua, '('):]
91            nav1=nav[string.find(nav,')'):]
92            bt['versOpera']=string.split(nav1,"/")[2]
93    except:pass
94   
95    bt['isMac'] = string.find(ua, 'Macintosh') > -1
96    bt['isWin'] = string.find(ua, 'Windows') > -1
97    bt['isIEWin'] = bt['isIE'] and bt['isWin']
98    bt['isIEMac'] = bt['isIE'] and bt['isMac']
99    bt['staticHTML'] = False
100
101    return bt
102
103def getParentPath(path, cnt=1):
104    """returns pathname shortened by cnt"""
105    # make sure path doesn't end with /
106    path = path.rstrip('/')
107    # split by /, shorten, and reassemble
108    return '/'.join(path.split('/')[0:-cnt])
109
110
111##
112## documentViewer class
113##
114class documentViewer(Folder):
115    """document viewer"""
116    meta_type="Document viewer"
117   
118    security=ClassSecurityInfo()
119    manage_options=Folder.manage_options+(
120        {'label':'main config','action':'changeDocumentViewerForm'},
121        )
122   
123    metadataService = None
124    """MetaDataFolder instance"""
125
126    # templates and forms
127    viewer_text = PageTemplateFile('zpt/viewer_text', globals())
128    viewer_images = PageTemplateFile('zpt/viewer_images', globals())
129    viewer_main = PageTemplateFile('zpt/viewer_main', globals())
130    toc_thumbs = PageTemplateFile('zpt/toc_thumbs', globals())
131    toc_text = PageTemplateFile('zpt/toc_text', globals())
132    toc_figures = PageTemplateFile('zpt/toc_figures', globals())
133    page_main_images = PageTemplateFile('zpt/page_main_images', globals())
134    page_main_double = PageTemplateFile('zpt/page_main_double', globals())
135    page_main_text = PageTemplateFile('zpt/page_main_text', globals())
136    page_main_text_dict = PageTemplateFile('zpt/page_main_text_dict', globals())
137    page_main_gis =PageTemplateFile ('zpt/page_main_gis', globals())
138    page_main_xml = PageTemplateFile('zpt/page_main_xml', globals())
139    page_main_pureXml = PageTemplateFile('zpt/page_main_pureXml', globals())
140    head_main = PageTemplateFile('zpt/head_main', globals())
141    info_xml = PageTemplateFile('zpt/info_xml', globals())
142    # TODO: can this be nicer?
143    docuviewer_css = ZSimpleFile(content_type='text/css',filename='css/docuviewer.css', id='docuviewer_css',_prefix=globals())
144   
145   
146    thumbs_main_rss = PageTemplateFile('zpt/thumbs_main_rss', globals())
147
148   
149    def __init__(self,id,imageScalerUrl=None,textServerName=None,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=5,authgroups="mpiwg"):
150        """init document viewer"""
151        self.id=id
152        self.title=title
153        self.thumbcols = thumbcols
154        self.thumbrows = thumbrows
155        # authgroups is list of authorized groups (delimited by ,)
156        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
157        # create template folder so we can always use template.something
158       
159        templateFolder = Folder('template')
160        #self['template'] = templateFolder # Zope-2.12 style
161        self._setObject('template',templateFolder) # old style
162        try:
163            import MpdlXmlTextServer
164            textServer = MpdlXmlTextServer.MpdlXmlTextServer(id='fulltextclient',serverName=textServerName)
165            #templateFolder['fulltextclient'] = xmlRpcClient
166            templateFolder._setObject('fulltextclient',textServer)
167        except Exception, e:
168            logging.error("Unable to create MpdlXmlTextServer for fulltextclient: "+str(e))
169           
170        try:
171            from Products.zogiLib.zogiLib import zogiLib
172            zogilib = zogiLib(id="zogilib", title="zogilib for docuviewer", dlServerURL=imageScalerUrl, layout="book")
173            #templateFolder['zogilib'] = zogilib
174            templateFolder._setObject('zogilib',zogilib)
175        except Exception, e:
176            logging.error("Unable to create zogiLib for zogilib: "+str(e))
177           
178        try:
179            # assume MetaDataFolder instance is called metadata
180            self.metadataService = getattr(self, 'metadata')
181        except Exception, e:
182            logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
183           
184        if digilibBaseUrl is not None:
185            self.digilibBaseUrl = digilibBaseUrl
186           
187       
188    # proxy text server methods to fulltextclient
189    def getTextPage(self, **args):
190        """get page"""
191        return self.template.fulltextclient.getTextPage(**args)
192
193    def getOrigPages(self, **args):
194        """get page"""
195        return self.template.fulltextclient.getOrigPages(**args)
196   
197    def getOrigPagesNorm(self, **args):
198        """get page"""
199        return self.template.fulltextclient.getOrigPagesNorm(**args)
200
201    def getQuery(self, **args):
202        """get query in search"""
203        return self.template.fulltextclient.getQuery(**args)
204     
205    def getSearch(self, **args):
206        """get search"""
207        return self.template.fulltextclient.getSearch(**args)
208   
209    def getGisPlaces(self, **args):
210        """get gis places"""
211        return self.template.fulltextclient.getGisPlaces(**args)
212 
213    def getAllGisPlaces(self, **args):
214        """get all gis places """
215        return self.template.fulltextclient.getAllGisPlaces(**args)
216       
217    def getWordInfo(self, **args):
218        """get translate"""
219        return self.template.fulltextclient.getWordInfo(**args)
220
221    def getLemma(self, **args):
222        """get lemma"""
223        return self.template.fulltextclient.getLemma(**args)
224
225    def getLemmaQuery(self, **args):
226        """get query"""
227        return self.template.fulltextclient.getLemmaQuery(**args)
228
229    def getLex(self, **args):
230        """get lex"""
231        return self.template.fulltextclient.getLex(**args)
232
233    def getToc(self, **args):
234        """get toc"""
235        return self.template.fulltextclient.getToc(**args)
236
237    def getTocPage(self, **args):
238        """get tocpage"""
239        return self.template.fulltextclient.getTocPage(**args)
240
241   
242    security.declareProtected('View','thumbs_rss')
243    def thumbs_rss(self,mode,url,viewMode="auto",start=None,pn=1):
244        '''
245        view it
246        @param mode: defines how to access the document behind url
247        @param url: url which contains display information
248        @param viewMode: if images display images, if text display text, default is images (text,images or auto)
249       
250        '''
251        logging.debug("HHHHHHHHHHHHHH:load the rss")
252        logging.debug("documentViewer (index) mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
253       
254        if not hasattr(self, 'template'):
255            # create template folder if it doesn't exist
256            self.manage_addFolder('template')
257           
258        if not self.digilibBaseUrl:
259            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
260           
261        docinfo = self.getDocinfo(mode=mode,url=url)
262        #pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo)
263        pageinfo = self.getPageinfo(start=start,current=pn, docinfo=docinfo)
264        ''' ZDES '''
265        pt = getattr(self.template, 'thumbs_main_rss')
266       
267        if viewMode=="auto": # automodus gewaehlt
268            if docinfo.has_key("textURL") or docinfo.get('textURLPath',None): #texturl gesetzt und textViewer konfiguriert
269                viewMode="text"
270            else:
271                viewMode="images"
272               
273        return pt(docinfo=docinfo,pageinfo=pageinfo,viewMode=viewMode)
274
275 
276    security.declareProtected('View','index_html')
277    def index_html(self,url,mode="texttool",viewMode="auto",viewType=None,tocMode="thumbs",start=1,pn=1):
278        """
279        view page
280        @param url: url which contains display information
281        @param mode: defines how to access the document behind url
282        @param viewMode: 'images': display images, 'text': display text, default is 'auto'
283        @param viewType: sub-type of viewMode, e.g. 'dict' for viewMode='text'
284        @param tocMode: type of 'table of contents' for navigation (thumbs, text, figures, none)
285        """
286       
287        logging.debug("documentViewer(index_html) mode=%s url=%s viewMode=%s viewType=%s start=%s pn=%s"%(mode,url,viewMode,viewType,start,pn))
288       
289        if not hasattr(self, 'template'):
290            # this won't work
291            logging.error("template folder missing!")
292            return "ERROR: template folder missing!"
293           
294        if not getattr(self, 'digilibBaseUrl', None):
295            self.digilibBaseUrl = self.findDigilibUrl() or "http://digilib.mpiwg-berlin.mpg.de/digitallibrary"
296           
297        docinfo = self.getDocinfo(mode=mode,url=url)
298       
299        if tocMode != "thumbs":
300            # get table of contents
301            docinfo = self.getToc(mode=tocMode, docinfo=docinfo)
302
303        # auto viewMode: text if there is a text else images
304        if viewMode=="auto": 
305            if docinfo.get('textURL', None) or docinfo.get('textURLPath', None): 
306                viewMode = "text"
307                viewType = "dict"
308            else:
309                viewMode = "images"
310               
311        elif viewMode == "text_dict":
312            # legacy fix
313            viewMode = "text"
314            viewType = "dict"
315           
316        # stringify viewType
317        if isinstance(viewType, list):
318            logging.debug("index_html: viewType is list:%s"%viewType)
319            viewType = ','.join([t for t in viewType if t])
320                       
321        pageinfo = self.getPageinfo(start=start, current=pn, docinfo=docinfo, viewMode=viewMode, viewType=viewType, tocMode=tocMode)
322                   
323        # get template /template/viewer_$viewMode
324        pt = getattr(self.template, 'viewer_%s'%viewMode, None)
325        if pt is None:
326            logging.error("No template for viewMode=%s!"%viewMode)
327            # TODO: error page?
328            return "No template for viewMode=%s!"%viewMode
329       
330        # and execute with parameters
331        return pt(docinfo=docinfo, pageinfo=pageinfo)
332 
333    def generateMarks(self,mk):
334        ret=""
335        if mk is None:
336            return ""
337        if not isinstance(mk, list):
338            mk=[mk]
339        for m in mk:
340            ret+="mk=%s"%m
341        return ret
342   
343   
344    def getBrowser(self):
345        """getBrowser the version of browser """
346        bt = browserCheck(self)
347        logging.debug("BROWSER VERSION: %s"%(bt))
348        return bt
349       
350    def findDigilibUrl(self):
351        """try to get the digilib URL from zogilib"""
352        url = self.template.zogilib.getDLBaseUrl()
353        return url
354   
355    def getScalerUrl(self, fn=None, pn=None, dw=100, dh=100, docinfo=None):
356        """returns URL to digilib Scaler with params"""
357        url = None
358        if docinfo is not None:
359            url = docinfo.get('imageURL', None)
360           
361        if url is None:
362            url = "%s/servlet/Scaler?"%self.digilibBaseUrl
363            if fn is None and docinfo is not None:
364                fn = docinfo.get('imagePath','')
365           
366            url += "fn=%s"%fn
367           
368        if pn:
369            url += "&pn=%s"%pn
370           
371        url += "&dw=%s&dh=%s"%(dw,dh)
372        return url
373
374    def getDocumentViewerURL(self):
375        """returns the URL of this instance"""
376        return self.absolute_url()
377   
378    def getStyle(self, idx, selected, style=""):
379        """returns a string with the given style and append 'sel' if idx == selected."""
380        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
381        if idx == selected:
382            return style + 'sel'
383        else:
384            return style
385   
386    def getParams(self, param=None, val=None, params=None, duplicates=None):
387        """returns dict with URL parameters.
388       
389        Takes URL parameters and additionally param=val or dict params.
390        Deletes key if value is None."""
391        # copy existing request params
392        newParams=self.REQUEST.form.copy()
393        # change single param
394        if param is not None:
395            if val is None:
396                if newParams.has_key(param):
397                    del newParams[param]
398            else:
399                newParams[param] = str(val)
400               
401        # change more params
402        if params is not None:
403            for (k, v) in params.items():
404                if v is None:
405                    # val=None removes param
406                    if newParams.has_key(k):
407                        del newParams[k]
408                       
409                else:
410                    newParams[k] = v
411
412        if duplicates:
413            # eliminate lists (coming from duplicate keys)
414            for (k,v) in newParams.items():
415                if isinstance(v, list):
416                    if duplicates == 'comma':
417                        # make comma-separated list of non-empty entries
418                        newParams[k] = ','.join([t for t in v if t])
419                    elif duplicates == 'first':
420                        # take first non-empty entry
421                        newParams[k] = [t for t in v if t][0]
422       
423        return newParams
424   
425    def getLink(self, param=None, val=None, params=None, baseUrl=None, paramSep='&', duplicates='comma'):
426        """returns URL to documentviewer with parameter param set to val or from dict params"""
427        urlParams = self.getParams(param=param, val=val, params=params, duplicates=duplicates)
428        # quote values and assemble into query string (not escaping '/')
429        ps = paramSep.join(["%s=%s"%(k,urllib.quote_plus(unicode(v),'/')) for (k, v) in urlParams.items()])
430        if baseUrl is None:
431            baseUrl = self.getDocumentViewerURL()
432           
433        url = "%s?%s"%(baseUrl, ps)
434        return url
435
436    def getLinkAmp(self, param=None, val=None, params=None, baseUrl=None, duplicates='comma'):
437        """link to documentviewer with parameter param set to val"""
438        return self.getLink(param=param, val=val, params=params, baseUrl=baseUrl, paramSep='&', duplicates=duplicates)
439   
440   
441    def getInfo_xml(self,url,mode):
442        """returns info about the document as XML"""
443        if not self.digilibBaseUrl:
444            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
445       
446        docinfo = self.getDocinfo(mode=mode,url=url)
447        pt = getattr(self.template, 'info_xml')
448        return pt(docinfo=docinfo)
449
450    def isAccessible(self, docinfo):
451        """returns if access to the resource is granted"""
452        access = docinfo.get('accessType', None)
453        logging.debug("documentViewer (accessOK) access type %s"%access)
454        if access == 'free':
455            logging.debug("documentViewer (accessOK) access is free")
456            return True
457       
458        elif access is None or access in self.authgroups:
459            # only local access -- only logged in users
460            user = getSecurityManager().getUser()
461            logging.debug("documentViewer (accessOK) user=%s ip=%s"%(user,self.REQUEST.getClientAddr()))
462            if user is not None:
463                #print "user: ", user
464                return (user.getUserName() != "Anonymous User")
465            else:
466                return False
467       
468        logging.error("documentViewer (accessOK) unknown access type %s"%access)
469        return False
470   
471
472
473    def getDocinfo(self, mode, url):
474        """returns docinfo depending on mode"""
475        logging.debug("getDocinfo: mode=%s, url=%s"%(mode,url))
476        # look for cached docinfo in session
477        if self.REQUEST.SESSION.has_key('docinfo'):
478            docinfo = self.REQUEST.SESSION['docinfo']
479            # check if its still current
480            if docinfo is not None and docinfo.get('mode', None) == mode and docinfo.get('url', None) == url:
481                logging.debug("getDocinfo: docinfo in session. keys=%s"%docinfo.keys())
482                return docinfo
483           
484        # new docinfo
485        docinfo = {'mode': mode, 'url': url}
486        # add self url
487        docinfo['viewerUrl'] = self.getDocumentViewerURL()
488        docinfo['digilibBaseUrl'] = self.digilibBaseUrl
489        # get index.meta DOM
490        docUrl = None
491        metaDom = None
492        if mode=="texttool": 
493            # url points to document dir or index.meta
494            metaDom = self.metadataService.getDomFromPathOrUrl(url)
495            docUrl = url.replace('/index.meta', '')
496            if metaDom is None:
497                raise IOError("Unable to find index.meta for mode=texttool!")
498
499        elif mode=="imagepath":
500            # url points to folder with images, index.meta optional
501            # asssume index.meta in parent dir
502            docUrl = getParentPath(url)
503            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
504
505        elif mode=="filepath":
506            # url points to image file, index.meta optional
507            # asssume index.meta is two path segments up
508            docUrl = getParentPath(url, 2)
509            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
510
511        else:
512            logging.error("documentViewer (getdocinfo) unknown mode: %s!"%mode)
513            raise ValueError("Unknown mode %s! Has to be one of 'texttool','imagepath','filepath'."%(mode))
514       
515        docinfo['documentUrl'] = docUrl
516        # process index.meta contents
517        if metaDom is not None and metaDom.tag == 'resource':
518            # document directory name and path
519            resource = self.metadataService.getResourceData(dom=metaDom)
520            if resource:
521                docinfo = self.getDocinfoFromResource(docinfo, resource)
522
523            # texttool info
524            texttool = self.metadataService.getTexttoolData(dom=metaDom)
525            if texttool:
526                docinfo = self.getDocinfoFromTexttool(docinfo, texttool)
527           
528            # bib info
529            bib = self.metadataService.getBibData(dom=metaDom)
530            if bib:
531                docinfo = self.getDocinfoFromBib(docinfo, bib)
532            else:
533                # no bib - try info.xml
534                docinfo = self.getDocinfoFromPresentationInfoXml(docinfo)
535               
536            # auth info
537            access = self.metadataService.getAccessData(dom=metaDom)
538            if access:
539                docinfo = self.getDocinfoFromAccess(docinfo, access)
540
541            # attribution info
542            attribution = self.metadataService.getAttributionData(dom=metaDom)
543            if attribution:
544                logging.debug("getDocinfo: attribution=%s"%repr(attribution))
545                docinfo['attribution'] = attribution
546                #docinfo = self.getDocinfoFromAccess(docinfo, access)
547
548            # copyright info
549            copyright = self.metadataService.getCopyrightData(dom=metaDom)
550            if copyright:
551                logging.debug("getDocinfo: copyright=%s"%repr(copyright))
552                docinfo['copyright'] = copyright
553                #docinfo = self.getDocinfoFromAccess(docinfo, access)
554
555        # image path
556        if mode != 'texttool':
557            # override image path from texttool with url
558            docinfo['imagePath'] = url.replace('/mpiwg/online/', '', 1)
559
560        # number of images from digilib
561        if docinfo.get('imagePath', None):
562            docinfo['imageURL'] = self.digilibBaseUrl + "/servlet/Scaler?fn=" + docinfo['imagePath']
563            docinfo = self.getDocinfoFromDigilib(docinfo, docinfo['imagePath'])
564
565        logging.debug("documentViewer (getdocinfo) docinfo: keys=%s"%docinfo.keys())
566        #logging.debug("documentViewer (getdocinfo) docinfo: %s"%docinfo)
567        # store in session
568        self.REQUEST.SESSION['docinfo'] = docinfo
569        return docinfo
570
571    def getDocinfoFromResource(self, docinfo, resource):
572        """reads contents of resource element into docinfo"""
573        docName = resource.get('name', None)
574        docinfo['documentName'] = docName
575        docPath = resource.get('archive-path', None)
576        if docPath:
577            # clean up document path
578            if docPath[0] != '/':
579                docPath = '/' + docPath
580               
581            if docName and (not docPath.endswith(docName)):
582                docPath += "/" + docName
583           
584        else:
585            # use docUrl as docPath
586            docUrl = docinfo['documentURL']
587            if not docUrl.startswith('http:'):
588                docPath = docUrl
589        if docPath:
590            # fix URLs starting with /mpiwg/online
591            docPath = docPath.replace('/mpiwg/online', '', 1)
592
593        docinfo['documentPath'] = docPath
594        return docinfo
595
596    def getDocinfoFromTexttool(self, docinfo, texttool):
597        """reads contents of texttool element into docinfo"""
598        # image dir
599        imageDir = texttool.get('image', None)
600        docPath = docinfo.get('documentPath', None)
601        if imageDir and docPath:
602            #print "image: ", imageDir, " archivepath: ", archivePath
603            imageDir = os.path.join(docPath, imageDir)
604            imageDir = imageDir.replace('/mpiwg/online', '', 1)
605            docinfo['imagePath'] = imageDir
606       
607        # old style text URL
608        textUrl = texttool.get('text', None)
609        if textUrl and docPath:
610            if urlparse.urlparse(textUrl)[0] == "": #keine url
611                textUrl = os.path.join(docPath, textUrl) 
612           
613            docinfo['textURL'] = textUrl
614   
615        # new style text-url-path
616        textUrl = texttool.get('text-url-path', None)
617        if textUrl:
618            docinfo['textURLPath'] = textUrl
619           
620        # page flow
621        docinfo['pageFlow'] = texttool.get('page-flow', 'ltr')
622           
623        # odd pages are left
624        docinfo['oddPage'] = texttool.get('odd-scan-position', 'left')
625           
626        # number of title page (0: not defined)
627        docinfo['titlePage'] = texttool.get('title-scan-no', 0)
628           
629        # old presentation stuff
630        presentation = texttool.get('presentation', None)
631        if presentation and docPath:
632            if presentation.startswith('http:'):
633                docinfo['presentationUrl'] = presentation
634            else:
635                docinfo['presentationUrl'] = os.path.join(docPath, presentation)
636           
637       
638        return docinfo
639
640    def getDocinfoFromBib(self, docinfo, bib):
641        """reads contents of bib element into docinfo"""
642        logging.debug("getDocinfoFromBib bib=%s"%repr(bib))
643        # put all raw bib fields in dict "bib"
644        docinfo['bib'] = bib
645        bibtype = bib.get('@type', None)
646        docinfo['bibType'] = bibtype
647        # also store DC metadata for convenience
648        dc = self.metadataService.getDCMappedData(bib)
649        docinfo['creator'] = dc.get('creator',None)
650        docinfo['title'] = dc.get('title',None)
651        docinfo['date'] = dc.get('date',None)
652        return docinfo
653           
654    def getDocinfoFromAccess(self, docinfo, acc):
655        """reads contents of access element into docinfo"""
656        #TODO: also read resource type
657        logging.debug("getDocinfoFromAccess acc=%s"%repr(acc))
658        try:
659            acctype = acc['@attr']['type']
660            if acctype:
661                access=acctype
662                if access in ['group', 'institution']:
663                    access = acc['name'].lower()
664               
665                docinfo['accessType'] = access
666
667        except:
668            pass
669       
670        return docinfo
671
672    def getDocinfoFromDigilib(self, docinfo, path):
673        infoUrl=self.digilibBaseUrl+"/dirInfo-xml.jsp?mo=dir&fn="+path
674        # fetch data
675        txt = getHttpData(infoUrl)
676        if not txt:
677            logging.error("Unable to get dir-info from %s"%(infoUrl))
678            return docinfo
679
680        dom = ET.fromstring(txt)
681        size = getText(dom.find("size"))
682        logging.debug("getDocinfoFromDigilib: size=%s"%size)
683        if size:
684            docinfo['numPages'] = int(size)
685        else:
686            docinfo['numPages'] = 0
687           
688        # TODO: produce and keep list of image names and numbers
689        return docinfo
690           
691           
692    def getDocinfoFromPresentationInfoXml(self,docinfo):
693        """gets DC-like bibliographical information from the presentation entry in texttools"""
694        url = docinfo.get('presentationUrl', None)
695        if not url:
696            logging.error("getDocinfoFromPresentation: no URL!")
697            return docinfo
698       
699        dom = None
700        metaUrl = None
701        if url.startswith("http://"):
702            # real URL
703            metaUrl = url
704        else:
705            # online path
706           
707            server=self.digilibBaseUrl+"/servlet/Texter?fn="
708            metaUrl=server+url
709       
710        txt=getHttpData(metaUrl)
711        if txt is None:
712            logging.error("Unable to read info.xml from %s"%(url))
713            return docinfo
714           
715        dom = ET.fromstring(txt)
716        docinfo['creator']=getText(dom.find(".//author"))
717        docinfo['title']=getText(dom.find(".//title"))
718        docinfo['date']=getText(dom.find(".//date"))
719        return docinfo
720   
721
722    def getPageinfo(self, current=None, start=None, rows=None, cols=None, docinfo=None, viewMode=None, viewType=None, tocMode=None):
723        """returns pageinfo with the given parameters"""
724        logging.debug("getPageInfo(current=%s, start=%s, rows=%s, cols=%s, viewMode=%s, viewType=%s, tocMode=%s)"%(current,start,rows,cols,viewMode,viewType,tocMode))
725        pageinfo = {}
726        pageinfo['viewMode'] = viewMode
727        pageinfo['viewType'] = viewType
728        pageinfo['tocMode'] = tocMode
729
730        current = getInt(current)
731        pageinfo['current'] = current
732        pageinfo['pn'] = current
733        rows = int(rows or self.thumbrows)
734        pageinfo['rows'] = rows
735        cols = int(cols or self.thumbcols)
736        pageinfo['cols'] = cols
737        grpsize = cols * rows
738        pageinfo['groupsize'] = grpsize
739        # is start is empty use one around current
740        start = getInt(start, default=(math.ceil(float(current)/float(grpsize))*grpsize-(grpsize-1)))
741        # int(current / grpsize) * grpsize +1))
742        pageinfo['start'] = start
743       
744        np = int(docinfo.get('numPages', 0))
745        if np == 0:
746            # numPages unknown - maybe we can get it from text page
747            if docinfo.get('textURLPath', None):
748                # cache text page as well
749                pageinfo['textPage'] = self.getTextPage(mode=viewType, pn=current, docinfo=docinfo, pageinfo=pageinfo)
750                np = int(docinfo.get('numPages', 0))
751               
752        pageinfo['numgroups'] = int(np / grpsize)
753        if np % grpsize > 0:
754            pageinfo['numgroups'] += 1
755
756        pageFlowLtr = docinfo.get('pageFlow', 'ltr') != 'rtl'
757        oddScanLeft = docinfo.get('oddPage', 'left') != 'right'
758        # add zeroth page for two columns
759        pageZero = (cols == 2 and (pageFlowLtr != oddScanLeft))
760        pageinfo['pageZero'] = pageZero
761        pageinfo['pageBatch'] = self.getPageBatch(start=start, rows=rows, cols=cols, pageFlowLtr=pageFlowLtr, pageZero=pageZero, minIdx=1, maxIdx=np)
762               
763        # TODO: do we need this here?
764        pageinfo['characterNormalization'] = self.REQUEST.get('characterNormalization','reg')
765        pageinfo['query'] = self.REQUEST.get('query','') 
766        pageinfo['queryType'] = self.REQUEST.get('queryType','')
767        pageinfo['querySearch'] =self.REQUEST.get('querySearch', 'fulltext')
768        pageinfo['highlightQuery'] = self.REQUEST.get('highlightQuery','')
769        pageinfo['tocPageSize'] = getInt(self.REQUEST.get('tocPageSize', 30))
770        pageinfo['queryPageSize'] = getInt(self.REQUEST.get('queryPageSize', 10))
771        pageinfo['tocPN'] = getInt(self.REQUEST.get('tocPN', '1'))
772        pageinfo['searchPN'] = getInt(self.REQUEST.get('searchPN','1'))
773       
774        # limit tocPN
775        if 'tocSize_%s'%tocMode in docinfo:
776            tocSize = docinfo['tocSize_%s'%tocMode]
777            tocPageSize = pageinfo['tocPageSize']
778            # cached toc           
779            if tocSize%tocPageSize>0:
780                tocPages=tocSize/tocPageSize+1
781            else:
782                tocPages=tocSize/tocPageSize
783               
784            pageinfo['tocPN'] = min(tocPages,pageinfo['tocPN'])
785           
786        return pageinfo
787
788
789    def getPageBatch(self, start=1, rows=10, cols=2, pageFlowLtr=True, pageZero=False, minIdx=1, maxIdx=0):
790        """returns dict with array of page informations for one screenfull of thumbnails"""
791        batch = {}
792        grpsize = rows * cols
793        if maxIdx == 0:
794            maxIdx = start + grpsize
795
796        nb = int(math.ceil(maxIdx / float(grpsize)))
797        # list of all batch start and end points
798        batches = []
799        if pageZero:
800            ofs = 0
801        else:
802            ofs = 1
803           
804        for i in range(nb):
805            s = i * grpsize + ofs
806            e = min((i + 1) * grpsize + ofs - 1, maxIdx)
807            batches.append({'start':s, 'end':e})
808           
809        batch['batches'] = batches
810
811        pages = []
812        if pageZero and start == 1:
813            # correct beginning
814            idx = 0
815        else:
816            idx = start
817           
818        for r in range(rows):
819            row = []
820            for c in range(cols):
821                if idx < minIdx or idx > maxIdx:
822                    page = {'idx':None}
823                else:
824                    page = {'idx':idx}
825                   
826                idx += 1
827                if pageFlowLtr:
828                    row.append(page)
829                else:
830                    row.insert(0, page) 
831               
832            pages.append(row)
833           
834        if start > 1:
835            batch['prevStart'] = max(start - grpsize, 1)
836        else:
837            batch['prevStart'] = None
838           
839        if start + grpsize < maxIdx:
840            batch['nextStart'] = start + grpsize
841        else:
842            batch['nextStart'] = None
843
844        batch['pages'] = pages
845        return batch
846       
847    def getBatch(self, start=1, size=10, end=0, data=None, fullData=True):
848        """returns dict with information for one screenfull of data."""
849        batch = {}
850        if end == 0:
851            end = start + size                   
852           
853        nb = int(math.ceil(end / float(size)))
854        # list of all batch start and end points
855        batches = []
856        for i in range(nb):
857            s = i * size + 1
858            e = min((i + 1) * size, end)
859            batches.append({'start':s, 'end':e})
860           
861        batch['batches'] = batches
862        # list of elements in this batch
863        this = []
864        j = 0
865        for i in range(start, min(start+size, end)):
866            if data:
867                if fullData:
868                    d = data[i]
869                else:
870                    d = data[j]
871                    j += 1
872           
873            else:
874                d = i+1
875               
876            this.append(d)
877           
878        batch['this'] = this
879        if start > 1:
880            batch['prevStart'] = max(start - size, 1)
881        else:
882            batch['prevStart'] = None
883           
884        if start + size < end:
885            batch['nextStart'] = start + size
886        else:
887            batch['nextStart'] = None
888       
889        return batch
890       
891
892    security.declareProtected('View management screens','changeDocumentViewerForm')   
893    changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
894   
895    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',RESPONSE=None):
896        """init document viewer"""
897        self.title=title
898        self.digilibBaseUrl = digilibBaseUrl
899        self.thumbrows = thumbrows
900        self.thumbcols = thumbcols
901        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
902        try:
903            # assume MetaDataFolder instance is called metadata
904            self.metadataService = getattr(self, 'metadata')
905        except Exception, e:
906            logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
907
908        if RESPONSE is not None:
909            RESPONSE.redirect('manage_main')
910       
911def manage_AddDocumentViewerForm(self):
912    """add the viewer form"""
913    pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
914    return pt()
915 
916def manage_AddDocumentViewer(self,id,imageScalerUrl="",textServerName="",title="",RESPONSE=None):
917    """add the viewer"""
918    newObj=documentViewer(id,imageScalerUrl=imageScalerUrl,title=title,textServerName=textServerName)
919    self._setObject(id,newObj)
920   
921    if RESPONSE is not None:
922        RESPONSE.redirect('manage_main')
Note: See TracBrowser for help on using the repository browser.