source: documentViewer/documentViewer.py @ 631:0c3aab828864

Last change on this file since 631:0c3aab828864 was 631:0c3aab828864, checked in by Dirk Wintergruen <dwinter@…>, 9 years ago

remove index meta ns

File size: 49.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
7
8import xml.etree.ElementTree as ET
9
10import os
11import urllib
12import logging
13import math
14import urlparse 
15import json
16
17from Products.MetaDataProvider import MetaDataFolder
18
19from SrvTxtUtils import getInt, utf8ify, getText, getHttpData, refreshingImageFileIndexHtml, sslifyUrl
20   
21
22INDEXMETA_NS="http://md.mpiwg-berlin.mpg.de/ns/indexMeta#"
23
24def removeINDEXMETA_NS(root): #entfernt den namespace von indexmeta aus dem dom #TODO evertyhing should be changed that it can deal with NS
25    for elem in root.getiterator():
26        print ("ETAG")
27        print(elem.tag)
28        if not hasattr(elem.tag, 'find'): continue  # (1)
29       
30        i = elem.tag.find('{%s}'%INDEXMETA_NS)
31        if i >= 0:
32            elem.tag = elem.tag[i+len(('{%s}'%INDEXMETA_NS)):]
33
34        print(elem.tag)
35
36def getMDText(node):
37    """returns the @text content from the MetaDataProvider metadata node"""
38    if isinstance(node, dict):
39        return node.get('@text', None)
40   
41    if isinstance(node,list): #more than one text file if there is an attribute don't choose it
42        for nodeInList in node:
43            attr = nodeInList.get("@attr",None)
44            if attr is None:
45                return node.get('@text',None)
46        return None
47
48    return node
49
50def getParentPath(path, cnt=1):
51    """returns pathname shortened by cnt"""
52    # make sure path doesn't end with /
53    path = path.rstrip('/')
54    # split by /, shorten, and reassemble
55    return '/'.join(path.split('/')[0:-cnt])
56
57def getPnForPf(docinfo, pf, default=0):
58    """returns image number for image file name or default"""
59    if 'imgFileNames' in docinfo:
60        pn = docinfo['imgFileNames'].get(pf, None)
61        if pn is None:
62            # try to cut extension
63            xi = pf.rfind('.')
64            if xi > 0:
65                pf = pf[:xi]
66                # try again, else return 0
67                pn = docinfo['imgFileNames'].get(pf, default)
68            else:
69                # no extension
70                pn = default
71               
72        return pn
73   
74    return default
75
76def getPfForPn(docinfo, pn, default=None):
77    """returns image file name for image number or default"""
78    if 'imgFileIndexes' in docinfo:
79        pn = docinfo['imgFileIndexes'].get(pn, default)
80        return pn
81   
82    return default
83
84
85##
86## documentViewer class
87##
88class documentViewer(Folder):
89    """document viewer"""
90    meta_type="Document viewer"
91   
92    security=ClassSecurityInfo()
93    manage_options=Folder.manage_options+(
94        {'label':'Configuration','action':'changeDocumentViewerForm'},
95        )
96   
97    metadataService = None
98    """MetaDataFolder instance"""
99   
100
101    #
102    # templates and forms
103    #
104    # viewMode templates
105    viewer_text = PageTemplateFile('zpt/viewer/viewer_text', globals())
106    viewer_hocr = PageTemplateFile('zpt/viewer/viewer_hocr', globals())
107    viewer_xml = PageTemplateFile('zpt/viewer/viewer_xml', globals())
108    viewer_image = PageTemplateFile('zpt/viewer/viewer_image', globals())
109    viewer_index = PageTemplateFile('zpt/viewer/viewer_index', globals())
110    viewer_thumbs = PageTemplateFile('zpt/viewer/viewer_thumbs', globals())
111    viewer_indexonly = PageTemplateFile('zpt/viewer/viewer_indexonly', globals())
112    viewer_text_image = PageTemplateFile('zpt/viewer/viewer_text_image', globals())
113    # available layer types (annotator not default)
114    builtinLayers = {'text': ['dict','search','gis'],
115                     'xml': None, 'image': None, 'index': ['extended'],'text_image': ['dict'],}
116    availableLayers = builtinLayers;
117    # layer templates
118    layer_text_dict = PageTemplateFile('zpt/viewer/layer_text_dict', globals())
119    layer_text_image_dict = PageTemplateFile('zpt/viewer/layer_text_image_dict', globals())
120    layer_text_search = PageTemplateFile('zpt/viewer/layer_text_search', globals())
121    layer_text_annotator = PageTemplateFile('zpt/viewer/layer_text_annotator', globals())
122    layer_text_gis = PageTemplateFile('zpt/viewer/layer_text_gis', globals())
123    layer_text_pundit = PageTemplateFile('zpt/viewer/layer_text_pundit', globals())
124    layer_image_annotator = PageTemplateFile('zpt/viewer/layer_image_annotator', globals())
125    layer_image_search = PageTemplateFile('zpt/viewer/layer_image_search', globals())
126    layer_index_extended = PageTemplateFile('zpt/viewer/layer_index_extended', globals())
127    # toc templates
128    toc_thumbs = PageTemplateFile('zpt/viewer/toc_thumbs', globals())
129    toc_text = PageTemplateFile('zpt/viewer/toc_text', globals())
130    toc_figures = PageTemplateFile('zpt/viewer/toc_figures', globals())
131    toc_concordance = PageTemplateFile('zpt/viewer/toc_concordance', globals())
132    toc_notes = PageTemplateFile('zpt/viewer/toc_notes', globals())
133    toc_handwritten = PageTemplateFile('zpt/viewer/toc_handwritten', globals())
134    toc_none = PageTemplateFile('zpt/viewer/toc_none', globals())
135    # other templates
136    common_template = PageTemplateFile('zpt/viewer/common_template', globals())
137    info_xml = PageTemplateFile('zpt/viewer/info_xml', globals())
138    docuviewer_css = ImageFile('css/docuviewer.css',globals())
139    # make docuviewer_css refreshable for development
140    docuviewer_css.index_html = refreshingImageFileIndexHtml
141    docuviewer_ie_css = ImageFile('css/docuviewer_ie.css',globals())
142    # make docuviewer_ie_css refreshable for development
143    #docuviewer_ie_css.index_html = refreshingImageFileIndexHtml
144    jquery_js = ImageFile('js/jquery.js',globals())
145   
146   
147    def __init__(self,id,imageScalerUrl=None,textServerName=None,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=5,authgroups="mpiwg"):
148        """init document viewer"""
149        self.id=id
150        self.title=title
151        self.thumbcols = thumbcols
152        self.thumbrows = thumbrows
153        # authgroups is list of authorized groups (delimited by ,)
154        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
155        # create template folder so we can always use template.something
156       
157        templateFolder = Folder('template')
158        self['template'] = templateFolder # Zope-2.12 style
159        #self._setObject('template',templateFolder) # old style
160        try:
161            import MpdlXmlTextServer
162            textServer = MpdlXmlTextServer.MpdlXmlTextServer(id='fulltextclient',serverName=textServerName)
163            templateFolder['fulltextclient'] = textServer
164            #templateFolder._setObject('fulltextclient',textServer)
165        except Exception, e:
166            logging.error("Unable to create MpdlXmlTextServer for fulltextclient: "+str(e))
167           
168        try:
169            from Products.zogiLib.zogiLib import zogiLib
170            zogilib = zogiLib(id="zogilib", title="zogilib for docuviewer", dlServerURL=imageScalerUrl, layout="book")
171            templateFolder['zogilib'] = zogilib
172            #templateFolder._setObject('zogilib',zogilib)
173        except Exception, e:
174            logging.error("Unable to create zogiLib for 'zogilib': "+str(e))
175           
176        try:
177            # assume MetaDataFolder instance is called metadata
178            self.metadataService = getattr(self, 'metadata')
179        except Exception, e:
180            logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
181           
182        if digilibBaseUrl is not None:
183            self.digilibBaseUrl = digilibBaseUrl
184            self.digilibScalerUrl = digilibBaseUrl + '/servlet/Scaler'
185            self.digilibViewerUrl = digilibBaseUrl + '/jquery/digilib.html'
186           
187
188    # proxy text server methods to fulltextclient
189    def getTextPage(self, **args):
190        """returns full text content of page"""
191        return self.template.fulltextclient.getTextPage(**args)
192
193    def getSearchResults(self, **args):
194        """loads list of search results and stores XML in docinfo"""
195        return self.template.fulltextclient.getSearchResults(**args)
196
197    def getResultsPage(self, **args):
198        """returns one page of the search results"""
199        return self.template.fulltextclient.getResultsPage(**args)
200
201    def getTextInfo(self, **args):
202        """returns document info from the text server"""
203        return self.template.fulltextclient.getTextInfo(**args)
204
205    def getToc(self, **args):
206        """loads table of contents and stores XML in docinfo"""
207        return self.template.fulltextclient.getToc(**args)
208
209    def getTocPage(self, **args):
210        """returns one page of the table of contents"""
211        return self.template.fulltextclient.getTocPage(**args)
212
213    def getRepositoryType(self, **args):
214        """get repository type"""
215        return self.template.fulltextclient.getRepositoryType(**args)
216
217    def getTextDownloadUrl(self, **args):
218        """get URL to download the full text"""
219        return self.template.fulltextclient.getTextDownloadUrl(**args)
220 
221    def getPlacesOnPage(self, **args):
222        """get list of gis places on one page"""
223        return self.template.fulltextclient.getPlacesOnPage(**args)
224 
225    # Thumb list for CoolIris Plugin
226    thumbs_main_rss = PageTemplateFile('zpt/thumbs_main_rss', globals())
227    security.declareProtected('View','thumbs_rss')
228    def thumbs_rss(self,mode,url,viewMode="auto",start=None,pn=1):
229        '''
230        view it
231        @param mode: defines how to access the document behind url
232        @param url: url which contains display information
233        @param viewMode: image: display images, text: display text, default is auto (try text, else image)
234       
235        '''
236       
237        if not hasattr(self, 'template'):
238            # this won't work
239            logging.error("template folder missing!")
240            return "ERROR: template folder missing!"
241                       
242        if not self.digilibBaseUrl:
243            self.digilibBaseUrl = self.findDigilibUrl() or "http://digilib.mpiwg-berlin.mpg.de/digitallibrary"
244           
245        docinfo = self.getDocinfo(mode=mode,url=url)
246        #pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo)
247        pageinfo = self.getPageinfo(start=start,pn=pn, docinfo=docinfo)
248        ''' ZDES '''
249        pt = getattr(self.template, 'thumbs_main_rss')
250       
251        if viewMode=="auto": # automodus gewaehlt
252            if docinfo.has_key("textURL") or docinfo.get('textURLPath',None): #texturl gesetzt und textViewer konfiguriert
253                viewMode="text"
254            else:
255                viewMode="image"
256               
257        return pt(docinfo=docinfo,pageinfo=pageinfo,viewMode=viewMode)
258
259 
260    security.declareProtected('View','index_html')
261    def index_html(self, url, mode="texttool", viewMode="auto", viewLayer=None, tocMode=None, start=None, pn=None, pf=None):
262        """
263        show page
264        @param url: url which contains display information
265        @param mode: defines how to access the document behind url
266        @param viewMode: 'image': display images, 'text': display text, 'xml': display xml, default is 'auto', 'hocr' : hocr format
267        @param viewLayer: sub-type of viewMode, e.g. layer 'dict' for viewMode='text'
268        @param tocMode: type of 'table of contents' for navigation (thumbs, text, figures, none)
269        """
270       
271        logging.debug("documentViewer(index_html) mode=%s url=%s viewMode=%s viewLayer=%s start=%s pn=%s pf=%s"%(mode,url,viewMode,viewLayer,start,pn,pf))
272       
273        if not hasattr(self, 'template'):
274            # this won't work
275            logging.error("template folder missing!")
276            return "ERROR: template folder missing!"
277
278        if not getattr(self, 'digilibBaseUrl', None):
279            self.digilibBaseUrl = self.findDigilibUrl() or "http://digilib.mpiwg-berlin.mpg.de/digitallibrary"
280           
281        # mode=filepath should not have toc-thumbs
282        if tocMode is None:
283            if mode == "filepath":
284                tocMode = "none"
285            else:
286                tocMode = "thumbs"
287           
288        # docinfo: information about document (cached)
289        docinfo = self.getDocinfo(mode=mode,url=url,tocMode=tocMode)
290       
291        # userinfo: user settings (cached)
292        userinfo = self.getUserinfo()
293       
294        # auto viewMode: text if there is a text else images
295        if viewMode=="auto": 
296            if docinfo.get('textURLPath', None):
297                # docinfo.get('textURL', None) not implemented yet
298                viewMode = "text"
299                if viewLayer is None and 'viewLayer' not in userinfo:
300                    # use layer dict as default
301                    viewLayer = "dict"
302            else:
303                viewMode = "image"
304               
305        elif viewMode == "text_dict":
306            # legacy fix
307            viewMode = "text"
308            viewLayer = "dict"
309           
310        elif viewMode == 'images':
311            # legacy fix
312            viewMode = 'image'
313            self.REQUEST['viewMode'] = 'image'
314
315        # safe viewLayer in userinfo
316        userinfo['viewLayer'] = viewLayer
317               
318        # pageinfo: information about page (not cached)
319        pageinfo = self.getPageinfo(start=start, pn=pn, pf=pf, docinfo=docinfo, userinfo=userinfo, viewMode=viewMode, viewLayer=viewLayer, tocMode=tocMode)
320                   
321        # get template /template/viewer_$viewMode
322        pt = getattr(self.template, 'viewer_%s'%viewMode, None)
323        if pt is None:
324            logging.error("No template for viewMode=%s!"%viewMode)
325            # TODO: error page?
326            return "No template for viewMode=%s!"%viewMode
327       
328        # and execute with parameters
329        return pt(docinfo=docinfo, pageinfo=pageinfo)
330 
331    def getAvailableLayers(self):
332        """returns dict with list of available layers per viewMode"""
333        return self.availableLayers
334   
335    def findDigilibUrl(self):
336        """try to get the digilib URL from zogilib"""
337        url = self.template.zogilib.getDLBaseUrl()
338        return url
339   
340    def getScalerUrl(self, fn=None, pn=None, dw=100, dh=100, docinfo=None):
341        """returns URL to digilib Scaler with params"""
342        url = None
343        if docinfo is not None:
344            url = docinfo.get('imageURL', None)
345           
346        if url is None:
347            url = self.digilibScalerUrl
348            if fn is None and docinfo is not None:
349                fn = docinfo.get('imagePath','')
350           
351            url += "fn=%s"%fn
352           
353        if pn:
354            url += "&pn=%s"%pn
355           
356        url += "&dw=%s&dh=%s"%(dw,dh)
357        return sslifyUrl(url, self, force=True)
358
359    def getDocumentViewerURL(self):
360        """returns the URL of this instance"""
361        return self.absolute_url()
362   
363    def getStyle(self, idx, selected, style=""):
364        """returns a string with the given style and append 'sel' if idx == selected."""
365        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
366        if idx == selected:
367            return style + 'sel'
368        else:
369            return style
370   
371    def getParams(self, param=None, val=None, params=None, duplicates=None):
372        """returns dict with URL parameters.
373       
374        Takes URL parameters and additionally param=val or dict params.
375        Deletes key if value is None."""
376        # copy existing request params
377        newParams=self.REQUEST.form.copy()
378        # change single param
379        if param is not None:
380            if val is None:
381                if newParams.has_key(param):
382                    del newParams[param]
383            else:
384                newParams[param] = str(val)
385               
386        # change more params
387        if params is not None:
388            for (k, v) in params.items():
389                if v is None:
390                    # val=None removes param
391                    if newParams.has_key(k):
392                        del newParams[k]
393                       
394                else:
395                    newParams[k] = v
396
397        if duplicates:
398            # eliminate lists (coming from duplicate keys)
399            for (k,v) in newParams.items():
400                if isinstance(v, list):
401                    if duplicates == 'comma':
402                        # make comma-separated list of non-empty entries
403                        newParams[k] = ','.join([t for t in v if t])
404                    elif duplicates == 'first':
405                        # take first non-empty entry
406                        newParams[k] = [t for t in v if t][0]
407       
408        return newParams
409   
410    def getLink(self, param=None, val=None, params=None, baseUrl=None, paramSep='&', duplicates='comma'):
411        """returns URL to documentviewer with parameter param set to val or from dict params"""
412        urlParams = self.getParams(param=param, val=val, params=params, duplicates=duplicates)
413        # quote values and assemble into query string (not escaping '/')
414        ps = paramSep.join(["%s=%s"%(k, urllib.quote_plus(utf8ify(v), '/')) for (k, v) in urlParams.items()])
415        if baseUrl is None:
416            baseUrl = self.getDocumentViewerURL()
417           
418        url = "%s?%s"%(baseUrl, ps)
419        return url
420
421    def getLinkAmp(self, param=None, val=None, params=None, baseUrl=None, duplicates='comma'):
422        """link to documentviewer with parameter param set to val"""
423        return self.getLink(param=param, val=val, params=params, baseUrl=baseUrl, paramSep='&amp;', duplicates=duplicates)
424   
425
426    def setAvailableLayers(self, newLayerString=None):
427        """sets availableLayers to newLayerString or tries to autodetect available layers.
428        assumes layer templates have the form layer_{m}_{l} for layer l in mode m.
429        newLayerString is parsed as JSON."""
430        if newLayerString is not None:
431            try:
432                layers = json.loads(newLayerString)
433                if 'text' in layers and 'image' in layers:
434                    self.availableLayers = layers
435                    return
436            except:
437                pass
438
439            logging.error("invalid layers=%s! autodetecting..."%repr(newLayerString))
440           
441        # start with builtin layers
442        self.availableLayers = self.builtinLayers.copy()
443        # add layers from templates
444        for t in self.template:
445            if t.startswith('layer_'):
446                try:
447                    (x, m, l) = t.split('_', 3)
448                    if m not in self.availableLayers:
449                        # mode m doesn't exist -> new list
450                        self.availableLayers[m] = [l]
451                       
452                    else:
453                        # m exists -> append
454                        if l not in self.availableLayers[m]:
455                            self.availableLayers[m].append()
456                           
457                except:
458                    pass
459
460    def getAvailableLayersJson(self):
461        """returns available layers as JSON string."""
462        return json.dumps(self.availableLayers)
463   
464   
465    def getInfo_xml(self,url,mode):
466        """returns info about the document as XML"""
467        if not self.digilibBaseUrl:
468            self.digilibBaseUrl = self.findDigilibUrl() or "http://digilib.mpiwg-berlin.mpg.de/digitallibrary"
469       
470        docinfo = self.getDocinfo(mode=mode,url=url)
471        pt = getattr(self.template, 'info_xml')
472        return pt(docinfo=docinfo)
473
474    def getAuthenticatedUser(self, anon=None):
475        """returns the authenticated user object or None. (ignores Zopes anonymous user)"""
476        user = getSecurityManager().getUser()
477        if user is not None and user.getUserName() != "Anonymous User":
478            return user
479        else:
480            return anon
481
482    def isAccessible(self, docinfo):
483        """returns if access to the resource is granted"""
484        access = docinfo.get('accessType', None)
485        logging.debug("documentViewer (accessOK) access type %s"%access)
486        if access == 'free':
487            logging.debug("documentViewer (accessOK) access is free")
488            return True
489       
490        elif access is None or access in self.authgroups:
491            # only local access -- only logged in users
492            user = self.getAuthenticatedUser()
493            logging.debug("documentViewer (accessOK) user=%s ip=%s"%(user,self.REQUEST.getClientAddr()))
494            return (user is not None)
495       
496        logging.error("documentViewer (accessOK) unknown access type %s"%access)
497        return False
498
499    def getUserinfo(self):
500        """returns userinfo object"""
501        logging.debug("getUserinfo")
502        userinfo = {}
503        # look for cached userinfo in session
504        if self.REQUEST.SESSION.has_key('userinfo'):
505            userinfo = self.REQUEST.SESSION['userinfo']
506            # check if its still current?
507        else:
508            # store in session
509            self.REQUEST.SESSION['userinfo'] = userinfo
510           
511        return userinfo
512
513    def getDocinfoJSON(self, mode, url, tocMode=None):
514        """returns docinfo depending on mode"""
515        import json
516       
517        dc = self.getDocinfo( mode, url, tocMode)
518       
519        return json.dumps(dc)
520   
521   
522    def getDocinfo(self, mode, url, tocMode=None):
523        """returns docinfo depending on mode"""
524        logging.debug("getDocinfo: mode=%s, url=%s"%(mode,url))
525        # look for cached docinfo in session
526        if self.REQUEST.SESSION.has_key('docinfo'):
527            docinfo = self.REQUEST.SESSION['docinfo']
528            # check if its still current
529            if docinfo is not None and docinfo.get('mode', None) == mode and docinfo.get('url', None) == url:
530                logging.debug("getDocinfo: docinfo in session. keys=%s"%docinfo.keys())
531                return docinfo
532           
533        # new docinfo
534        docinfo = {'mode': mode, 'url': url}
535        # add self url
536        docinfo['viewerUrl'] = self.getDocumentViewerURL()
537        docinfo['digilibBaseUrl'] = sslifyUrl(self.digilibBaseUrl, self, force=True)
538        docinfo['digilibScalerUrl'] = sslifyUrl(self.digilibScalerUrl, self, force=True)
539        docinfo['digilibViewerUrl'] = sslifyUrl(self.digilibViewerUrl, self, force=True)
540        # get index.meta DOM
541        docUrl = None
542        metaDom = None
543        if mode=="texttool": 
544            # url points to document dir or index.meta
545            metaDom = self.metadataService.getDomFromPathOrUrl(url)
546            removeINDEXMETA_NS(metaDom)
547
548            if metaDom is None:
549                raise IOError("Unable to find index.meta for mode=texttool!")
550           
551            docUrl = url.replace('/index.meta', '')
552            if url.startswith('/mpiwg/online/'):
553                docUrl = url.replace('/mpiwg/online/', '', 1)
554        elif mode=="textpath":
555            #url points to an textfile
556            #index.meta optional
557            #assume index.meta in parent dir
558            docUrl = getParentPath(url)
559            docinfo['viewmode'] = "text"
560           
561            try:
562                metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
563
564                removeINDEXMETA_NS(metaDom)
565
566
567               
568            except:
569                metaDom = None
570            #metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
571            #docinfo['imagePath'] = url.replace('/mpiwg/online', '', 1)
572            docinfo['textURLPath'] = url.replace('/mpiwg/online', '', 1)
573            docinfo['textURL'] = url
574            if docinfo.get("creator", None) is None:
575                docinfo['creator'] = "" 
576           
577            if docinfo.get("title", None) is None:
578                docinfo['title'] = "" 
579
580            if docinfo.get("documentPath", None) is None:
581                docinfo['documentPath'] = url.replace('/mpiwg/online', '', 1)
582                docinfo['documentPath'] = url.replace('/pages', '', 1)
583               
584            docinfo['numPages'] = 1
585
586        elif mode=="imagepath":
587            # url points to folder with images, index.meta optional
588            # asssume index.meta in parent dir
589           
590            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
591           
592            docinfo['imagePath'] = url.replace('/mpiwg/online', '', 1)
593           
594        elif mode=="hocr":
595            # url points to folder with images, index.meta optional
596            # asssume index.meta in parent dir
597            docUrl = getParentPath(url)
598            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
599            docinfo['imagePath'] = url.replace('/mpiwg/online', '', 1)
600            docinfo['textURLPath'] = url.replace('/mpiwg/online', '', 1)
601            if docinfo.get("creator", None) is None:
602                docinfo['creator'] = "" 
603           
604            if docinfo.get("title", None) is None:
605                docinfo['title'] = "" 
606
607            if docinfo.get("documentPath", None) is None:
608                docinfo['documentPath'] = url.replace('/mpiwg/online', '', 1)
609                docinfo['documentPath'] = url.replace('/pages', '', 1)
610
611        elif mode=="filepath":
612            # url points to image file, index.meta optional
613            docinfo['imageURL'] = "%s?fn=%s"%(self.digilibScalerUrl, url)
614            docinfo['numPages'] = 1
615            # asssume index.meta is two path segments up
616            docUrl = getParentPath(url, 2)
617            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
618
619        else:
620            logging.error("documentViewer (getdocinfo) unknown mode: %s!"%mode)
621            raise ValueError("Unknown mode %s! Has to be one of 'texttool','imagepath','filepath'."%(mode))
622       
623        docinfo['documentUrl'] = docUrl
624        # process index.meta contents
625       
626        if metaDom is not None and (metaDom.tag == 'resource' or metaDom.tag == "{%s}resource"%INDEXMETA_NS):
627            print("MD")
628            # document directory name and path
629            resource = self.metadataService.getResourceData(dom=metaDom, recursive=1)
630            if resource:
631                docinfo = self.getDocinfoFromResource(docinfo, resource)
632           
633            # texttool info
634            texttool = self.metadataService.getTexttoolData(dom=metaDom, recursive=1, all=True)
635            if texttool:
636                docinfo = self.getDocinfoFromTexttool(docinfo, texttool)
637                # document info from full text server
638                if docinfo.get('textURLPath', None):
639                    docinfo = self.getTextInfo(mode=None, docinfo=docinfo)
640                    # include list of pages TODO: do we need this always?
641                    docinfo = self.getTextInfo(mode='pages', docinfo=docinfo)
642           
643            # bib info
644            bib = self.metadataService.getBibData(dom=metaDom)
645            if bib:
646                # save extended version as 'bibx' TODO: ugly
647                bibx = self.metadataService.getBibData(dom=metaDom, all=True, recursive=1)
648                if len(bibx) == 1:
649                    # unwrap list if possible
650                    bibx = bibx[0]
651                   
652                docinfo['bibx'] = bibx
653                docinfo = self.getDocinfoFromBib(docinfo, bib, bibx)
654            else:
655                # no bib - try info.xml
656                docinfo = self.getDocinfoFromPresentationInfoXml(docinfo)
657               
658            # auth info
659            access = self.metadataService.getAccessData(dom=metaDom)
660            if access:
661                docinfo = self.getDocinfoFromAccess(docinfo, access)
662
663            # attribution info
664            attribution = self.metadataService.getAttributionData(dom=metaDom)
665            if attribution:
666                logging.debug("getDocinfo: attribution=%s"%repr(attribution))
667                docinfo['attribution'] = attribution
668
669            # copyright info
670            copyright = self.metadataService.getCopyrightData(dom=metaDom)
671            if copyright:
672                logging.debug("getDocinfo: copyright=%s"%repr(copyright))
673                docinfo['copyright'] = copyright
674
675            # DRI (permanent ID)
676            dri = self.metadataService.getDRI(dom=metaDom, type='mpiwg')
677            if dri:
678                docinfo['DRI'] = dri
679
680            # (presentation) context
681            ctx = self.metadataService.getContextData(dom=metaDom, all=True)
682            if ctx:
683                logging.debug("getcontext: ctx=%s"%repr(ctx))
684                docinfo['presentationContext'] = ctx
685
686        # image path
687        if mode != 'texttool':
688            # override image path from texttool with url parameter TODO: how about mode=auto?
689            docinfo['imagePath'] = url.replace('/mpiwg/online', '', 1)
690
691        # check numPages
692        if docinfo.get('numPages', 0) == 0:
693            # number of images from digilib
694            if docinfo.get('imagePath', None):
695                imgpath = docinfo['imagePath'].replace('/mpiwg/online', '', 1)
696                logging.debug("imgpath=%s"%imgpath)
697                docinfo['imageURL'] = sslifyUrl("%s?fn=%s"%(self.digilibScalerUrl, imgpath), self, force=True)
698                docinfo = self.getDocinfoFromDigilib(docinfo, imgpath)
699            else:
700                # imagePath still missing? try "./pageimg"
701                imgPath = os.path.join(docUrl, 'pageimg')
702                docinfo = self.getDocinfoFromDigilib(docinfo, imgPath)
703                if docinfo.get('numPages', 0) > 0:
704                    # there are pages
705                    docinfo['imagePath'] = imgPath
706                    docinfo['imageURL'] = sslifyUrl("%s?fn=%s"%(self.digilibScalerUrl, docinfo['imagePath']), self, force=True)
707
708        # check numPages
709        if docinfo.get('numPages', 0) == 0:
710            if docinfo.get('numTextPages', 0) > 0:
711                # replace with numTextPages (text-only?)
712                docinfo['numPages'] = docinfo['numTextPages']
713               
714        # min and max page no
715        docinfo['minPageNo'] = docinfo.get('minPageNo', 1)
716        docinfo['maxPageNo'] = docinfo.get('maxPageNo', docinfo['numPages'])
717
718        # part-of information
719        partOfPath = docinfo.get('partOfPath', None)
720        if partOfPath is not None:
721            partOfDom = self.metadataService.getDomFromPathOrUrl(partOfPath)
722            if partOfDom is not None:
723                docinfo['partOfLabel'] = self.metadataService.getBibFormattedLabel(dom=partOfDom)
724                docinfo['partOfUrl'] = "%s?url=%s"%(self.getDocumentViewerURL(), partOfPath)
725                logging.debug("partOfLabel=%s partOfUrl=%s"%(docinfo['partOfLabel'],docinfo['partOfUrl']))
726
727        # normalize path
728        if 'imagePath' in docinfo and not docinfo['imagePath'].startswith('/'):
729            docinfo['imagePath'] = '/' + docinfo['imagePath']
730
731        logging.debug("documentViewer (getdocinfo) docinfo: keys=%s"%docinfo.keys())
732        # store in session
733        self.REQUEST.SESSION['docinfo'] = docinfo
734        return docinfo
735
736
737    def getDocinfoFromResource(self, docinfo, resource):
738        """reads contents of resource element into docinfo"""
739        logging.debug("getDocinfoFromResource: resource=%s"%(repr(resource)))
740        docName = getMDText(resource.get('name', None))
741        docinfo['documentName'] = docName
742        docPath = getMDText(resource.get('archive-path', None))
743        if docPath:
744            # clean up document path
745            if docPath[0] != '/':
746                docPath = '/' + docPath
747               
748            if docName and (not docPath.endswith(docName)):
749                docPath += "/" + docName
750           
751        else:
752            # use docUrl as docPath
753            docUrl = docinfo['documentURL']
754            if not docUrl.startswith('http:'):
755                docPath = docUrl
756               
757        if docPath:
758            # fix URLs starting with /mpiwg/online
759            docPath = docPath.replace('/mpiwg/online', '', 1)
760
761        docinfo['documentPath'] = docPath
762       
763        # is this part-of?
764        partOf = resource.get('is-part-of', None)
765        if partOf is not None:
766            partOf = getMDText(partOf.get('archive-path', None))
767            if partOf is not None:
768                docinfo['partOfPath'] = partOf.strip()
769               
770        return docinfo
771
772    def getDocinfoFromTexttool(self, docinfo, texttool):
773        """reads contents of texttool element into docinfo"""
774        logging.debug("texttool=%s"%repr(texttool))
775        # unpack list if necessary
776        if isinstance(texttool, list):
777            texttool = texttool[0]
778                                   
779        # image dir
780        imageDir = getMDText(texttool.get('image', None))
781        docPath = getMDText(docinfo.get('documentPath', None))
782        if imageDir:
783            if imageDir.startswith('/'):
784                # absolute path
785                imageDir = imageDir.replace('/mpiwg/online', '', 1)
786                docinfo['imagePath'] = imageDir
787               
788            elif docPath:
789                # relative path
790                imageDir = os.path.join(docPath, imageDir)
791                imageDir = imageDir.replace('/mpiwg/online', '', 1)
792                docinfo['imagePath'] = imageDir
793               
794        # start and end page (for subdocuments of other documents)
795        imgStartNo = getMDText(texttool.get('image-start-no', None))           
796        minPageNo = getInt(imgStartNo, 1)
797        docinfo['minPageNo'] = minPageNo
798
799        imgEndNo = getMDText(texttool.get('image-end-no', None))
800        if imgEndNo:
801            docinfo['maxPageNo'] = getInt(imgEndNo)
802       
803        # old style text URL
804        textUrl = getMDText(texttool.get('text', None))
805
806        if textUrl and docPath:
807            if urlparse.urlparse(textUrl)[0] == "": #keine url
808                textUrl = os.path.join(docPath, textUrl) 
809           
810            docinfo['textURL'] = textUrl
811   
812        # new style text-url-path (can be more than one with "repository" attribute)
813        textUrlNode = texttool.get('text-url-path', None)
814        if not isinstance(textUrlNode, list):
815            textUrlNode = [textUrlNode]
816
817        for tun in textUrlNode:
818            textUrl = getMDText(tun)
819            if textUrl:
820                textUrlAtts = tun.get('@attr')
821                if (textUrlAtts and 'repository' in textUrlAtts):
822                    textRepo = textUrlAtts['repository']
823                    # use matching repository
824                    if self.getRepositoryType() == textRepo:
825                        docinfo['textURLPath'] = textUrl
826                        docinfo['textURLRepository'] = textRepo
827                        break
828               
829                else:
830                    # no repo attribute - use always
831                    docinfo['textURLPath'] = textUrl
832           
833        # page flow
834        docinfo['pageFlow'] = getMDText(texttool.get('page-flow', 'ltr'))
835           
836        # odd pages are left
837        docinfo['oddPage'] = getMDText(texttool.get('odd-scan-position', 'left'))
838           
839        # number of title page (default 1)
840        docinfo['titlePage'] = getMDText(texttool.get('title-scan-no', minPageNo))
841           
842        # old presentation stuff
843        presentation = getMDText(texttool.get('presentation', None))
844        if presentation and docPath:
845            if presentation.startswith('http:'):
846                docinfo['presentationUrl'] = presentation
847            else:
848                docinfo['presentationUrl'] = os.path.join(docPath, presentation)
849               
850        # make sure we have at least fake DC data
851        if 'creator' not in docinfo:
852            docinfo['creator'] = '[no author found]'
853           
854        if 'title' not in docinfo:
855            docinfo['title'] = '[no title found]'
856           
857        if 'date' not in docinfo:
858            docinfo['date'] = '[no date found]'
859       
860        return docinfo
861
862    def getDocinfoFromBib(self, docinfo, bib, bibx=None):
863        """reads contents of bib element into docinfo"""
864        logging.debug("getDocinfoFromBib bib=%s"%repr(bib))
865        # put all raw bib fields in dict "bib"
866        docinfo['bib'] = bib
867        bibtype = bib.get('@type', None)
868        docinfo['bibType'] = bibtype
869        # also store DC metadata for convenience
870        dc = self.metadataService.getDCMappedData(bib)
871        docinfo['creator'] = dc.get('creator','')
872        docinfo['title'] = dc.get('title','')
873        docinfo['date'] = dc.get('date','')
874        return docinfo
875           
876    def getDocinfoFromAccess(self, docinfo, acc):
877        """reads contents of access element into docinfo"""
878        #TODO: also read resource type
879        logging.debug("getDocinfoFromAccess acc=%s"%repr(acc))
880        try:
881            acctype = acc['@attr']['type']
882            if acctype:
883                access=acctype
884                if access in ['group', 'institution']:
885                    access = acc['name'].lower()
886               
887                docinfo['accessType'] = access
888
889        except:
890            pass
891       
892        return docinfo
893
894    def getDocinfoFromDigilib(self, docinfo, path):
895        infoUrl=self.digilibBaseUrl+"/dirInfo-xml.jsp?fn="+path
896        # fetch data
897        txt = getHttpData(infoUrl)
898        if not txt:
899            logging.error("Unable to get dir-info from %s"%(infoUrl))
900            return docinfo
901
902        dom = ET.fromstring(txt)
903        dir = dom
904        # save size
905        size = dir.findtext('size')
906        logging.debug("getDocinfoFromDigilib: size=%s"%size)
907        if size:
908            docinfo['numPages'] = int(size)
909        else:
910            docinfo['numPages'] = 0
911            return docinfo
912           
913        # save list of image names and numbers
914        imgNames = {}
915        imgIndexes = {}
916        for f in dir:
917            fn = f.findtext('name')
918            pn = getInt(f.findtext('index'))
919            imgNames[fn] = pn
920            imgIndexes[pn] = fn
921           
922        docinfo['imgFileNames'] = imgNames
923        docinfo['imgFileIndexes'] = imgIndexes
924        return docinfo
925           
926           
927    def getDocinfoFromPresentationInfoXml(self,docinfo):
928        """gets DC-like bibliographical information from the presentation entry in texttools"""
929        url = docinfo.get('presentationUrl', None)
930        if not url:
931            logging.error("getDocinfoFromPresentation: no URL!")
932            return docinfo
933       
934        dom = None
935        metaUrl = None
936        if url.startswith("http://"):
937            # real URL
938            metaUrl = url
939        else:
940            # online path
941            server=self.digilibBaseUrl+"/servlet/Texter?fn="
942            metaUrl=server+url
943       
944        txt=getHttpData(metaUrl)
945        if txt is None:
946            logging.error("Unable to read info.xml from %s"%(url))
947            return docinfo
948           
949        dom = ET.fromstring(txt)
950        docinfo['creator']=getText(dom.find(".//author"))
951        docinfo['title']=getText(dom.find(".//title"))
952        docinfo['date']=getText(dom.find(".//date"))
953        return docinfo
954   
955
956    def getPageinfo(self, pn=None, pf=None, start=None, rows=None, cols=None, docinfo=None, userinfo=None, viewMode=None, viewLayer=None, tocMode=None):
957        """returns pageinfo with the given parameters"""
958        logging.debug("getPageInfo(pn=%s, pf=%s, start=%s, rows=%s, cols=%s, viewMode=%s, viewLayer=%s, tocMode=%s)"%(pn,pf,start,rows,cols,viewMode,viewLayer,tocMode))
959        pageinfo = {}
960        pageinfo['viewMode'] = viewMode
961        # split viewLayer if necessary
962        if isinstance(viewLayer,basestring):
963            viewLayer = viewLayer.split(',')
964           
965        if isinstance(viewLayer, list):
966            logging.debug("getPageinfo: viewLayer is list:%s"%viewLayer)
967            # save (unique) list in viewLayers
968            seen = set()
969            viewLayers = [l for l in viewLayer if l and l not in seen and not seen.add(l)]
970            pageinfo['viewLayers'] = viewLayers
971            # stringify viewLayer
972            viewLayer = ','.join(viewLayers)
973        else:
974            #create list
975            pageinfo['viewLayers'] = [viewLayer]
976                       
977        pageinfo['viewLayer'] = viewLayer
978        pageinfo['tocMode'] = tocMode
979
980        minPageNo = docinfo.get('minPageNo', 1)
981
982        # pf takes precedence over pn
983        if pf:
984            pageinfo['pf'] = pf
985            pn = getPnForPf(docinfo, pf)
986            # replace pf in request params (used for creating new URLs)
987            self.REQUEST.form.pop('pf', None)
988            self.REQUEST.form['pn'] = pn
989        else:
990            pn = getInt(pn, minPageNo)
991            pf = getPfForPn(docinfo, pn)
992            pageinfo['pf'] = pf
993           
994        pageinfo['pn'] = pn
995        rows = int(rows or self.thumbrows)
996        pageinfo['rows'] = rows
997        cols = int(cols or self.thumbcols)
998        pageinfo['cols'] = cols
999        grpsize = cols * rows
1000        pageinfo['groupsize'] = grpsize
1001        # if start is empty use one around pn
1002        grouppn = math.ceil(float(pn)/float(grpsize))*grpsize-(grpsize-1)
1003        # but not smaller than minPageNo
1004        start = getInt(start, max(grouppn, minPageNo))
1005        pageinfo['start'] = start
1006        # get number of pages
1007        numPages = int(docinfo.get('numPages', 0))
1008        if numPages == 0:
1009            # try numTextPages
1010            numPages = docinfo.get('numTextPages', 0)
1011            if numPages != 0:
1012                docinfo['numPages'] = numPages
1013
1014        maxPageNo = docinfo.get('maxPageNo', numPages)
1015        logging.debug("minPageNo=%s maxPageNo=%s start=%s numPages=%s"%(minPageNo,maxPageNo,start,numPages))
1016        np = maxPageNo
1017
1018        # cache table of contents
1019        pageinfo['tocPageSize'] = getInt(self.REQUEST.get('tocPageSize', 30))
1020        pageinfo['numgroups'] = int(np / grpsize)
1021        if np % grpsize > 0:
1022            pageinfo['numgroups'] += 1
1023
1024        pageFlowLtr = docinfo.get('pageFlow', 'ltr') != 'rtl'
1025        oddScanLeft = docinfo.get('oddPage', 'left') != 'right'
1026        # add zeroth page for two columns
1027        pageZero = (cols == 2 and (pageFlowLtr != oddScanLeft))
1028        pageinfo['pageZero'] = pageZero
1029        pageinfo['pageBatch'] = self.getPageBatch(start=start, rows=rows, cols=cols, pageFlowLtr=pageFlowLtr, pageZero=pageZero, minIdx=minPageNo, maxIdx=np)
1030        # more page parameters
1031        #pageinfo['characterNormalization'] = self.REQUEST.get('characterNormalization','reg')
1032        #becuase it is buggy this currently disabled and set to orig.
1033        pageinfo['characterNormalization'] = 'orig'
1034        if docinfo.get('pageNumbers'):
1035            # get original page numbers
1036            pageNumber = docinfo['pageNumbers'].get(pn, None)
1037            if pageNumber is not None:
1038                pageinfo['pageNumberOrig'] = pageNumber['no']
1039                pageinfo['pageNumberOrigNorm'] = pageNumber['non']
1040       
1041        # cache search results
1042        query = self.REQUEST.get('query',None)
1043        pageinfo['query'] = query
1044        if query and viewMode == 'text':
1045            pageinfo['resultPageSize'] = getInt(self.REQUEST.get('resultPageSize', 10))
1046            queryType = self.REQUEST.get('queryType', 'fulltextMorph')
1047            pageinfo['queryType'] = queryType
1048            pageinfo['resultStart'] = getInt(self.REQUEST.get('resultStart', '1'))
1049            self.getSearchResults(mode=queryType, query=query, pageinfo=pageinfo, docinfo=docinfo)
1050           
1051            # highlighting
1052            highlightQuery = self.REQUEST.get('highlightQuery', None)
1053            if highlightQuery:
1054                pageinfo['highlightQuery'] = highlightQuery
1055                pageinfo['highlightElement'] = self.REQUEST.get('highlightElement', '')
1056                pageinfo['highlightElementPos'] = self.REQUEST.get('highlightElementPos', '')
1057           
1058        return pageinfo
1059
1060
1061    def getPageBatch(self, start=1, rows=10, cols=2, pageFlowLtr=True, pageZero=False, minIdx=1, maxIdx=0):
1062        """Return dict with array of page information for one screenfull of thumbnails.
1063
1064        :param start: index of current page
1065        :param rows: number of rows in one batch
1066        :param cols: number of columns in one batch
1067        :param pageFlowLtr: do indexes increase from left to right
1068        :param pageZero: is there a zeroth non-visible page
1069        :param minIdx: minimum index to use
1070        :param maxIdx: maximum index to use
1071        :returns: dict with
1072            first: first page index
1073            last: last page index
1074            batches: list of all possible batches(dict: 'start': index, 'end': index)
1075            pages: list for current batch of rows(list of cols(list of pages(dict: 'idx': index)))
1076            nextStart: first index of next batch
1077            prevStart: first index of previous batch
1078        """
1079        logging.debug("getPageBatch start=%s minIdx=%s maxIdx=%s"%(start,minIdx,maxIdx))
1080        batch = {}
1081        grpsize = rows * cols
1082        if maxIdx == 0:
1083            maxIdx = start + grpsize
1084
1085        np = maxIdx - minIdx + 1
1086        if pageZero:
1087            # correct number of pages for batching
1088            np += 1
1089           
1090        nb = int(math.ceil(np / float(grpsize)))
1091       
1092        # list of all batch start and end points
1093        batches = []
1094        if pageZero:
1095            ofs = minIdx - 1
1096        else:
1097            ofs = minIdx
1098           
1099        for i in range(nb):
1100            s = i * grpsize + ofs
1101            e = min((i + 1) * grpsize + ofs - 1, maxIdx)
1102            batches.append({'start':s, 'end':e})
1103           
1104        batch['batches'] = batches
1105
1106        # list of pages for current screen
1107        pages = []
1108        if pageZero and start == minIdx:
1109            # correct beginning
1110            idx = minIdx - 1
1111        else:
1112            idx = start
1113           
1114        for r in range(rows):
1115            row = []
1116            for c in range(cols):
1117                if idx < minIdx or idx > maxIdx:
1118                    page = {'idx':None}
1119                else:
1120                    page = {'idx':idx}
1121                   
1122                idx += 1
1123                if pageFlowLtr:
1124                    row.append(page)
1125                else:
1126                    row.insert(0, page) 
1127               
1128            pages.append(row)
1129           
1130        if start > minIdx:
1131            batch['prevStart'] = max(start - grpsize, minIdx)
1132        else:
1133            batch['prevStart'] = None
1134           
1135        if start + grpsize <= maxIdx:
1136            if pageZero and start == minIdx:
1137                # correct nextStart for pageZero
1138                batch['nextStart'] = grpsize
1139            else:
1140                batch['nextStart'] = start + grpsize
1141        else:
1142            batch['nextStart'] = None
1143
1144        batch['pages'] = pages
1145        batch['first'] = minIdx
1146        batch['last'] = maxIdx
1147        logging.debug("batch: %s"%repr(batch))
1148        return batch
1149       
1150       
1151    def getBatch(self, start=1, size=10, end=0, data=None, fullData=True):
1152        """returns dict with information for one screenfull of data."""
1153        batch = {}
1154        if end == 0:
1155            end = start + size                   
1156           
1157        nb = int(math.ceil(end / float(size)))
1158        # list of all batch start and end points
1159        batches = []
1160        for i in range(nb):
1161            s = i * size + 1
1162            e = min((i + 1) * size, end)
1163            batches.append({'start':s, 'end':e})
1164           
1165        batch['batches'] = batches
1166        # list of elements in this batch
1167        this = []
1168        j = 0
1169        for i in range(start, min(start+size, end+1)):
1170            if data:
1171                if fullData:
1172                    d = data.get(i, None)
1173                else:
1174                    d = data.get(j, None)
1175                    j += 1
1176           
1177            else:
1178                d = i+1
1179               
1180            this.append(d)
1181           
1182        batch['this'] = this
1183        if start > 1:
1184            batch['prevStart'] = max(start - size, 1)
1185        else:
1186            batch['prevStart'] = None
1187           
1188        if start + size < end:
1189            batch['nextStart'] = start + size
1190        else:
1191            batch['nextStart'] = None
1192       
1193        batch['first'] = start
1194        batch['last'] = end
1195        return batch
1196       
1197
1198    def getAnnotatorGroupsForUser(self, user, annotationServerUrl="http://tuxserve03.mpiwg-berlin.mpg.de/AnnotationManager"):
1199        """returns list of groups {name:*, id:*} on the annotation server for the user"""
1200        groups = []
1201        # add matching http(s) from our URL
1202        annotationServerUrl = sslifyUrl(annotationServerUrl, self)
1203           
1204        groupsUrl = "%s/annotator/groups?user=%s"%(annotationServerUrl,user)
1205        data = getHttpData(url=groupsUrl, noExceptions=True)
1206        if data:
1207            res = json.loads(data)
1208            rows = res.get('rows', None)
1209            if rows is None:
1210                return groups
1211            for r in rows:
1212                groups.append({'id': r.get('id', None), 'name': r.get('name', None), 'uri': r.get('uri', None)})
1213               
1214        return groups
1215   
1216    def sslifyUrl(self, url, **args):
1217        """returns URL with http or https"""
1218        return sslifyUrl(url, **args)
1219
1220    security.declareProtected('View management screens','changeDocumentViewerForm')   
1221    changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
1222   
1223    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',availableLayers=None,RESPONSE=None):
1224        """init document viewer"""
1225        self.title=title
1226        self.digilibBaseUrl = digilibBaseUrl
1227        self.digilibScalerUrl = digilibBaseUrl + '/servlet/Scaler'
1228        self.digilibViewerUrl = digilibBaseUrl + '/jquery/digilib.html'
1229        self.thumbrows = thumbrows
1230        self.thumbcols = thumbcols
1231        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
1232        try:
1233            # assume MetaDataFolder instance is called metadata
1234            self.metadataService = getattr(self, 'metadata')
1235        except Exception, e:
1236            logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
1237           
1238        self.setAvailableLayers(availableLayers)
1239
1240        if RESPONSE is not None:
1241            RESPONSE.redirect('manage_main')
1242           
1243       
1244def manage_AddDocumentViewerForm(self):
1245    """add the viewer form"""
1246    pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
1247    return pt()
1248 
1249def manage_AddDocumentViewer(self,id,imageScalerUrl="",textServerName="",title="",RESPONSE=None):
1250    """add the viewer"""
1251    newObj=documentViewer(id,imageScalerUrl=imageScalerUrl,title=title,textServerName=textServerName)
1252    self._setObject(id,newObj)
1253   
1254    if RESPONSE is not None:
1255        RESPONSE.redirect('manage_main')
Note: See TracBrowser for help on using the repository browser.