source: MILK/trunk/milk_server/milk_server/models/DiscoveryState.py @ 5306

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/MILK/trunk/milk_server/milk_server/models/DiscoveryState.py@5306
Revision 5306, 7.1 KB checked in by cbyrom, 11 years ago (diff)

Add new template method, 'semanticSearch' to do the asynchronous
loading of alternative search options - and replace the previous
template code with this in both results pages. Fix a couple of issues
with the PagerState? object to ensure start/last page stride is set
correctly.

Line 
1from paste.request import parse_querystring
2from milk_server.lib.Utilities import getURLConstraints
3import cgi,urllib
4
5   
6def getURLFormattedConstraints(environ, **kw):
7    '''
8    Get the constraints in a url friendly string - modified by the keyword arguments
9    offset and stride which are to be part of the querystring
10    @param environ: wsgi environ object
11    @return constraints in a url friendly string
12    '''
13    args = dict(parse_querystring(environ))
14
15    constrained = kw.get('constrained')
16    if not constrained:
17        offset, stride = kw.get('offset'), kw.get('stride')
18        if offset:
19            args['start'] = offset
20        if stride:
21            args['howmany'] = stride
22
23    q = ''
24    for i in args:
25        # NB, the constraints may already be encoded as a hidden variable
26        if i != 'constraints':
27            q+='%s=%s&'%(i,args[i])
28
29    # add constraints last to avoid duplicate params - NB, constraint params
30    # can be overridden by direct inputs to the page
31    if 'constraints' in args:
32        constraints = getURLConstraints(args['constraints'])
33        for key, val in constraints.items():
34            if key not in args:
35                q+='%s=%s&'%(key, val)
36
37    return q[0:-1]
38
39
40def getURL(environ, **kw):
41    '''
42    Get a url from the wsgi environment
43    @param environ: wsgi environ object
44    @return url with constraints added from wsgi environ
45    '''
46    constraints = getURLFormattedConstraints(environ, **kw)
47    return urllib.quote(environ.get('SCRIPT_NAME','')) + \
48        urllib.quote(environ.get('PATH_INFO','')) + '?' + constraints
49
50
51class constraints:
52    '''
53    A container object for constraints on a search
54    '''
55    def __init__(self, **kw):
56        self.values={}
57        keys=['dateRange','bbox','scope','textTarget','searchString','geoSearchType']
58        for key in keys:
59            self.values[key]=None
60        for k in kw: 
61            self[k]=kw[k]
62           
63           
64    def __setitem__(self, key, value):
65        if key in self.values:
66            self.values[key]=value
67        else:
68            raise ValueError('Unknown key [%s] in constraints')
69
70   
71    def __getitem__(self,key):
72        if key in self.values: 
73            return self.values[key]
74        else:
75            raise ValueError('Unknown key [%s] in constraints'%key)
76
77   
78    def __str__(self):
79        c=''
80        if self.values['dateRange'] is not None:
81            dr = self.values['dateRange'] 
82            c += 'Date range: %s to %s'%('%s/%s/%s'%dr[0],'%s/%s/%s'%dr[1])
83        bbox=self.values['bbox']
84        if c:
85            c += ', '
86        c += 'Bounding box: '
87        if bbox is None or bbox==['90.0','-180.0','180.0','-90.0']:
88            c+='Global'
89        else:
90            overlaps = self.values['geoSearchType'] or 'overlaps'
91            c+='%s latitude %s to %sN and longitude %s to %sE' \
92                %(overlaps,bbox[3],bbox[0],bbox[1],bbox[2])
93        if self.values['scope']: 
94            c += 'Scope: %s'%self.values['scope']
95        if self.values['textTarget']:
96            c += 'Target: %s'%self.values['textTarget']
97        return c
98
99
100class PagerState:
101    '''
102    Object to hold the current page state of the displayed results - e.g. which
103    page number and how many records, before and after those displayed, are available
104    '''
105   
106    def __init__(self, hits, environ, offset=1, stride=10, defaultStride = 10):
107        '''
108        Initialise PagerState object
109        @param hits: total number of records available to view
110        @param environ: wsgi environ object   
111        @keyword offset: offset being used in the currently displayed record set
112        - i.e. the array number of the topmost record displayed. Default = 1
113        @keyword stride: Number of records currently visible.  Default = 10
114        @keyword defaultStride: Standard number of records to display on a page.
115        Default = 10
116        '''
117        self.hits = hits
118        self.offset = offset
119        self.stride = stride
120
121        self.previousPageURL = None
122        self.previousNumber = None
123        self.startPageURL = None
124        self.nextPageURL = None
125        self.nextNumber = None
126        self.lastPageURL = None
127       
128        self.defaultStride = defaultStride
129       
130        n, p = self.getNext()
131        start, end = "", ""
132        if p:
133            self.previousPageURL = getURL(environ, offset = p[0], stride = p[1])
134            self.previousNumber = p[1]
135            self.startPageURL = getURL(environ, offset = 1, stride = self.defaultStride)
136        if n:
137            self.nextPageURL = getURL(environ, offset = n[0], stride = n[1])
138            self.nextNumber = n[1]
139            off = self.hits - self.defaultStride + 1
140            if off < 1:
141                off = 1
142            self.lastPageURL = getURL(environ, offset = off, stride = self.defaultStride)
143           
144        self.upperRange = self.offset + self.stride - 1
145        self.lowerRange = self.offset
146       
147   
148    def getNext(self):
149        '''
150        Get info on what number of records are available on current page
151        @return result - list with format [[offSetForNextPage, numberOfRecordsOnNextPage],
152                                           [offSetForLastPage, numberOfRecordsOnLastPage]]
153        '''
154        result=[]
155        if self.offset+self.stride < self.hits:
156            #there are more to look at
157            r = [self.offset+self.stride, self.stride]
158            if r[0]+r[1]-1 > self.hits: 
159                r[1] = self.hits+1-r[0]
160            result.append(r)
161        else:
162            result.append([])
163           
164        if self.offset > 1:
165            #there are previous records
166            b = max(self.stride, self.defaultStride)
167            r = [self.offset-b,b]
168            if r[0] < 1: 
169                r[0] = 1
170            if r[1] > self.hits: 
171                r[1] = self.hits
172            result.append(r)
173        else: 
174            result.append([])
175        return result
176       
177   
178
179class DiscoveryState:
180    ''' This class holds the state associated with a search (including presenting multiple slices
181    of a large result set) '''
182    def __init__(self,sessionID,searchString,environ,hits,constraints,offset=1,stride=10):
183        ''' On instantiation, provide
184                the backend sessionID
185                the application URL that produced this query
186                the stride through the result set '''
187        self.environ=environ # the wsgi environment
188        self.constraintsInstance=constraints
189        self.constraints=str(constraints) # some text to show constraints on search
190        self.urlformattedconstraints = getURLFormattedConstraints(self.environ)
191        self.sessID=sessionID
192        self.hits=hits
193
194        self.searchString=searchString
195        self.alternatives=None
196        self.constrainedurl = getURL(self.environ, constrained=1)+'&constrained'
197        self.pager = PagerState(hits, self.environ, offset=offset, stride=stride)
198       
199    def __str__(self):
200        return '''
201___ Discovery State ___
202searchString: %s
203constraints: %s
204sessionID: %s
205hits: %s
206offset,stride: %s,%s
207environment: %s
208========================
209'''%(self.searchString,self.constraints,self.sessID,self.hits,self.offset,self.stride,self.environ)
Note: See TracBrowser for help on using the repository browser.