source: documentViewer/documentViewer.py @ 499:3f9703746fef

elementtree
Last change on this file since 499:3f9703746fef was 499:3f9703746fef, checked in by casties, 12 years ago

more cleanup. new template for viewMode=index (not pretty so far).

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