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

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

Simplify structure of discovery controller, using the results template
to render searches even when no results are found. Add new error
dict to avoid confusing with the error dict used by the formencode
input checker. Add additional input checks and improve error handling.
Add dropdown list to select order by values + add new constants
module to store associated data and error keys + tidy up DiscoveryState?
object to make clearer and logic more consistent + fix paging controls
for results data.

Line 
1from paste.request import parse_querystring
2from milk_server.lib.Utilities import getURLConstraints
3import cgi,urllib
4
5class constraints:
6    '''
7    A container object for constraints on a search
8    '''
9    def __init__(self, **kw):
10        self.values={}
11        keys=['dateRange','bbox','scope','textTarget','searchString','geoSearchType']
12        for key in keys:
13            self.values[key]=None
14        for k in kw: 
15            self[k]=kw[k]
16           
17           
18    def __setitem__(self, key, value):
19        if key in self.values:
20            self.values[key]=value
21        else:
22            raise ValueError('Unknown key [%s] in constraints')
23
24   
25    def __getitem__(self,key):
26        if key in self.values: 
27            return self.values[key]
28        else:
29            raise ValueError('Unknown key [%s] in constraints'%key)
30
31   
32    def __str__(self):
33        c=''
34        if self.values['dateRange'] is not None:
35            dr = self.values['dateRange'] 
36            c += 'Date range: %s to %s'%('%s/%s/%s'%dr[0],'%s/%s/%s'%dr[1])
37        bbox=self.values['bbox']
38        if c:
39            c += ', '
40        c += 'Bounding box: '
41        if bbox is None or bbox==['90.0','-180.0','180.0','-90.0']:
42            c+='Global'
43        else:
44            overlaps = self.values['geoSearchType'] or 'overlaps'
45            c+='%s latitude %s to %sN and longitude %s to %sE' \
46                %(overlaps,bbox[3],bbox[0],bbox[1],bbox[2])
47        if self.values['scope']: 
48            c += 'Scope: %s'%self.values['scope']
49        if self.values['textTarget']:
50            c += 'Target: %s'%self.values['textTarget']
51        return c
52
53
54class DiscoveryState:
55    ''' This class holds the state associated with a search (including presenting multiple slices
56    of a large result set) '''
57    def __init__(self,sessionID,searchString,environ,hits,constraints,offset=1,stride=10):
58        ''' On instantiation, provide
59                the backend sessionID
60                the application URL that produced this query
61                the stride through the result set '''
62        self.environ=environ # the wsgi environment
63        self.constraintsInstance=constraints
64        self.constraints=str(constraints) # some text to show constraints on search
65        self.urlformattedconstraints = self.__getURLFormattedConstraints()
66        self.sessID=sessionID
67        self.hits=hits
68        self.offset=offset
69        self.stride=stride
70        self.searchString=searchString
71        self.alternatives=None
72        self.constrainedurl=self.geturl(constrained=1)+'&constrained'
73
74   
75    def __getURLFormattedConstraints(self,**kw):
76        '''
77        Get the constraints in a url friendly string - modified by the keyword arguments
78        offset and stride which are to be part of the querystring
79        '''
80        args = dict(parse_querystring(self.environ))
81        offset, stride= kw.get('offset'), kw.get('stride')
82        if offset is not None:
83            args['start']=offset
84        if stride is not None:
85            args['howmany']=stride
86
87        constrained=kw.get('constrained')
88        if constrained is not None:
89            if 'start' in args: 
90                del args['start']
91            if 'howmany' in args: 
92                del args['howmany']
93
94        q = ''
95        for i in args:
96            # NB, the constraints may already be encoded as a hidden variable
97            if i != 'constraints':
98                q+='%s=%s&'%(i,args[i])
99
100        # add constraints last to avoid duplicate params - NB, constraint params
101        # can be overridden by direct inputs to the page
102        if i == 'constraints':
103            constraints = getURLConstraints(args[i])
104            for key, val in constraints.items():
105                if key not in args:
106                    q+='%s=%s&'%(key, val)
107
108        return q[0:-1]
109
110   
111    def geturl(self,**kw):
112        '''
113        Get a url from the wsgi environment
114        '''
115        constraints = self.__getURLFormattedConstraints(**kw)
116        return urllib.quote(self.environ.get('SCRIPT_NAME','')) + \
117            urllib.quote(self.environ.get('PATH_INFO','')) + '?' + constraints
118
119   
120    def getNext(self):
121        '''
122        Get info on what number of records are available on current page
123        @return result - list with format [[offSetForNextPage, numberOfRecordsOnNextPage],
124                                           [offSetForLastPage, numberOfRecordsOnLastPage]]
125        '''
126        result=[]
127        defStride=10
128        if self.offset+self.stride < self.hits:
129            #there are more to look at
130            r = [self.offset+self.stride, self.stride]
131            if r[0]+r[1]-1>self.hits: 
132                r[1] = self.hits+1-r[0]
133            result.append(r)
134        else:
135            result.append([])
136           
137        if self.offset > 1:
138            #there are previous records
139            b=max(self.stride, defStride)
140            r=[self.offset-b,b]
141            if r[0]<1: 
142                r[0]=1
143            if r[1]>self.hits: 
144                r[1]=self.hits
145            result.append(r)
146        else: 
147            result.append([])
148        return result
149       
150    def __str__(self):
151        return '''
152___ Discovery State ___
153searchString: %s
154constraints: %s
155sessionID: %s
156hits: %s
157offset,stride: %s,%s
158environment: %s
159========================
160'''%(self.searchString,self.constraints,self.sessID,self.hits,self.offset,self.stride,self.environ)
Note: See TracBrowser for help on using the repository browser.