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

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

Adjusted to handle problem with definition of bbox for global searches

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
87        c += 'Bounding box: '
88       
89        #Need to put workaround for browsers that dont let map window global search = 180 etc..
90        #if bbox is None or bbox==['90.0','-180.0','180.0','-90.0']:
91       
92        if bbox is None or ((float(bbox[0]) >= 89) & (float(bbox[1]) <= -179) & (float(bbox[2]) >= 179) & (float(bbox[3]) <= 89)):
93           
94            c+='Global'
95           
96        else:
97            overlaps = self.values['geoSearchType'] or 'overlaps'
98            c+='%s latitude %s to %sN and longitude %s to %sE' \
99                %(overlaps,bbox[3],bbox[0],bbox[1],bbox[2])
100               
101               
102           # c+='Global' # fudge sjd
103        if self.values['scope']:
104            if c:
105                c += ', ' 
106            c += 'Scope: %s'%self.values['scope']
107        if self.values['textTarget']:
108            if c:
109                c += ', ' 
110            c += 'Target: %s'%self.values['textTarget']
111        return c
112
113
114class PagerState:
115    '''
116    Object to hold the current page state of the displayed results - e.g. which
117    page number and how many records, before and after those displayed, are available
118    '''
119   
120    def __init__(self, hits, environ, offset=1, stride=10, defaultStride = 10):
121        '''
122        Initialise PagerState object
123        @param hits: total number of records available to view
124        @param environ: wsgi environ object   
125        @keyword offset: offset being used in the currently displayed record set
126        - i.e. the array number of the topmost record displayed. Default = 1
127        @keyword stride: Number of records currently visible.  Default = 10
128        @keyword defaultStride: Standard number of records to display on a page.
129        Default = 10
130        '''
131        self.hits = hits
132        self.offset = offset
133        self.stride = stride
134
135        self.previousPageURL = None
136        self.previousNumber = None
137        self.startPageURL = None
138        self.nextPageURL = None
139        self.nextNumber = None
140        self.lastPageURL = None
141       
142        self.defaultStride = defaultStride
143       
144        n, p = self.getNext()
145        start, end = "", ""
146        if p:
147            self.previousPageURL = getURL(environ, offset = p[0], stride = p[1])
148            self.previousNumber = p[1]
149            self.startPageURL = getURL(environ, offset = 1, stride = self.defaultStride)
150        if n:
151            self.nextPageURL = getURL(environ, offset = n[0], stride = n[1])
152            self.nextNumber = n[1]
153            off = self.hits - self.defaultStride + 1
154            if off < 1:
155                off = 1
156            self.lastPageURL = getURL(environ, offset = off, stride = self.defaultStride)
157           
158        self.upperRange = self.offset + self.stride - 1
159        self.lowerRange = self.offset
160       
161   
162    def getNext(self):
163        '''
164        Get info on what number of records are available on current page
165        @return result - list with format [[offSetForNextPage, numberOfRecordsOnNextPage],
166                                           [offSetForLastPage, numberOfRecordsOnLastPage]]
167        '''
168        result=[]
169        if self.offset+self.stride < self.hits:
170            #there are more to look at
171            r = [self.offset+self.stride, self.stride]
172            if r[0]+r[1]-1 > self.hits: 
173                r[1] = self.hits+1-r[0]
174            result.append(r)
175        else:
176            result.append([])
177           
178        if self.offset > 1:
179            #there are previous records
180            b = max(self.stride, self.defaultStride)
181            r = [self.offset-b,b]
182            if r[0] < 1: 
183                r[0] = 1
184            if r[1] > self.hits: 
185                r[1] = self.hits
186            result.append(r)
187        else: 
188            result.append([])
189        return result
190       
191   
192
193class DiscoveryState:
194    ''' This class holds the state associated with a search (including presenting multiple slices
195    of a large result set) '''
196    def __init__(self,sessionID,searchString,environ,hits,constraints,offset=1,stride=10):
197        ''' On instantiation, provide
198                the backend sessionID
199                the application URL that produced this query
200                the stride through the result set '''
201        self.environ=environ # the wsgi environment
202        self.constraintsInstance=constraints
203        self.constraints=str(constraints) # some text to show constraints on search
204        self.urlformattedconstraints = getURLFormattedConstraints(self.environ)
205        self.sessID=sessionID
206        self.hits=hits
207
208        self.searchString=searchString
209        self.alternatives=None
210        self.constrainedurl = getURL(self.environ, constrained=1)+'&constrained'
211        self.pager = PagerState(hits, self.environ, offset=offset, stride=stride)
212       
213    def __str__(self):
214        return '''
215___ Discovery State ___
216searchString: %s
217constraints: %s
218sessionID: %s
219hits: %s
220offset,stride: %s,%s
221environment: %s
222========================
223'''%(self.searchString,self.constraints,self.sessID,self.hits,self.offset,self.stride,self.environ)
Note: See TracBrowser for help on using the repository browser.