source: documentViewer/documentViewer.py @ 489:55e3398e395e

elementtree
Last change on this file since 489:55e3398e395e was 489:55e3398e395e, checked in by casties, 13 years ago

more new templates. monkey-patch for App.ImageFile?.

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