source: MILK/trunk/milk_server/milk_server/controllers/atom_editor/listatom.py @ 4625

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/MILK/trunk/milk_server/milk_server/controllers/atom_editor/listatom.py@4625
Revision 4625, 7.9 KB checked in by cbyrom, 11 years ago (diff)

Improve error handling in the atom controllers + refactor ndgInterface
to remove code from constructor to allow dependency injection - to
improve flexibility and testability. Also, change ambiguous naming
references in classes to minimise codeword overaps/confusion.

Line 
1'''
2 Class representing pylons controller for the listing and searching of atom
3 data
4 
5 @author: C Byrom, Tessella Sep 2008
6'''
7import logging, xmlrpclib
8from paste.request import parse_querystring
9from ndgUtils import ndgObject
10from ndgUtils.models.Atom import Atom
11from ndgUtils import DocumentRetrieve
12from ndgUtils.eXistInterface import ndg_eXist
13import ndgUtils.lib.existdbclient as edc
14from ndgUtils.models.MolesEntity import MolesEntity as ME
15from ndgUtils.vocabtermdata import VocabTermData as VTD, VocabTermItem as VTI
16from milk_server.lib.base import *
17import milk_server.lib.htmlUtilities as utils
18from milk_server.lib.atomutilities import savePageAndRender
19from editatom import EditatomController as ec
20
21
22class ListatomController(BaseController):
23    '''
24    Provides the pylons controller for listing/searching NDG Atom documents.
25    '''
26    def __setup(self,uri=None):
27        ''' Common setup stuff for all the actions on this controller '''
28        logging.info("Setting up EditatomController")
29        self.cf=request.environ['ndgConfig']
30       
31        if uri:
32            try:
33                self.ndgObject = ndgObject(uri, config=self.cf)
34            except ValueError,e:
35                return e
36
37        self.inputs=dict(parse_querystring(request.environ))
38
39        logging.info("EditatomController set up")
40        return 0
41
42
43    def atomHome(self):
44        '''
45        Render a simple home page for the atom editor
46        '''
47        logging.info("Rendering atom home page")
48        c.title = "Atom Editor Home Page"
49        return savePageAndRender(self.pathInfo, "atom_editor/atom_home")
50
51
52    def showExampleGranulite(self):
53        '''
54        Show an example granulite file
55        '''
56        logging.info("Rendering example granulite file page")
57        c.title = "Example granulite file"
58        return savePageAndRender(self.pathInfo, "atom_editor/granulite_example")
59   
60   
61    def list(self, searchData=None, associatedAtomID=None, \
62             associatedAtomType=None, associationType=None):
63        '''
64        Provide a simple search interface to the atoms data
65        - display a filter + display any results + if an atomID is
66        provided, allow atoms to be linked to this
67        @keyword associatedAtomID: the ID of an atom to which other atoms
68        should be linked - via deployments
69        @keyword associatedAtomType: type of atom that the data is being
70        associated with
71        @keyword associationType: type of association to be done - NB, use
72        the constants in htmlUtilities for these
73        '''
74        try:
75            inputs = request.params
76            c.searchData = None
77            if searchData and int(searchData) > 0:
78                logging.info("Preparing atom search")
79                c.searchData = searchData
80                self.__setup()
81                atomTypeID = inputs.get('atomTypeID')
82                providerID = inputs.get('providerID')
83                # NB, avoid page being reloaded in incorrect state - e.g. after
84                # browser reload
85                if not (atomTypeID and providerID):
86                    return self.list()
87                   
88                atomTypeID = atomTypeID.split('--')[1]
89                providerID = providerID.split('--')[1]
90               
91                # if we're dealing with activity deployments, substitute the typeID
92                # for the subType Deployments term
93                if atomTypeID == VTD.ACTIVITY_DEPLOYMENT_TERM:
94                    atomTypeID = VTD.DEPLOYMENT_TERM
95                   
96                c.results = self.searchAtoms(providerID, atomTypeID, inputs.get('title'))
97               
98            logging.info("Rendering atom listings page")
99            c.errors = {}
100            c.title='Browse atoms'
101            c.assocAtomType = associatedAtomType
102            c.associateLink = ""
103            if associatedAtomID:
104                c.associateLink = h.url_for(controller='atom_editor/editatom', action='saveAtom', \
105                    uri = associatedAtomID, saveLevel = ec.ADD_ASSOCIATIONS)
106            c.searchLink = h.url_for(controller = 'atom_editor/listatom', action='list', \
107                                     searchData='1', associatedAtomID = associatedAtomID)
108           
109            c.searchTerm = inputs.get('title')
110           
111            # set up the drop down content
112            # NB, if we are here whilst doing an association, restrict the filter
113            # appropriately
114            listVals = []
115            defaultVal = None
116            # set up a default 'all' value
117            allVal = VTI(ndg_eXist.DEFAULT_ALL_VAL, ndg_eXist.DEFAULT_ALL_VAL)
118            if associationType:
119                val = int(associationType)
120                if val == utils.GRANULE_ASSOCIATION:
121                    c.title += ' - to create associations with granule data'
122                    listVals = [g.vtd.TERM_DATA[g.vtd.GRANULE_TERM]]
123                elif val == utils.DEPLOYMENT_ASSOCIATION:
124                    c.title += ' - to create associations with deployment data'
125                    listVals = [g.vtd.TERM_DATA[g.vtd.DEPLOYMENT_TERM]]
126                elif val == utils.ENTITY_ASSOCIATION:
127                    c.title += ' - to create associations with activity/data production tool/observation station data'
128                    listVals = g.vtd.getValidTypes(g.vtd.DEPLOYABLE_ATOM_CATEGORY)
129                    defaultVal = allVal
130            else:
131                listVals = g.vtd.getValidTypes(g.vtd.ATOM_CATEGORY)
132                defaultVal = allVal
133           
134            c.atomTypes = utils.getVocabTermDataDropdown(listVals, \
135                                                   defaultVal = defaultVal, \
136                                                   selected = inputs.get('atomTypeID'))
137            c.providerIDs = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.PROVIDER_CATEGORY), 
138                                                     defaultVal = allVal, \
139                                                     selected = inputs.get('providerID'))
140
141            return savePageAndRender(self.pathInfo, 'atom_editor/atom_list')
142
143        except Exception, e:
144            c.xml='Unexpected error loading page [%s]' %str(e)
145            c.doc=''
146            logging.error(c.xml)
147       
148        response.status_code = 400
149        return render("genshi", 'atom_editor/error')
150   
151   
152    def searchAtoms(self, providerID, atomTypeID, term):
153        '''
154        Search for atoms with specified filter info
155        @param providerID: provider ID of atom or 'all' for all
156        @param atomTypeID: type of atom or 'all' for all
157        @param term: text to search for in atom
158        @return array of dicts with info for each doc found in search
159        '''
160        logging.info("Search for atoms with the following filter: \
161            \nProviderID: '%s'\nAtom Type: '%s'\nText in title: '%s'" \
162            %(providerID, atomTypeID, term))
163       
164        dr = DocumentRetrieve(self.cf.get('NDG_EXIST','local'),
165                              pwfile=self.cf.get('NDG_EXIST','passwordFile'))
166       
167        # NB, for some reason, the xmlrpc call to eXist sometimes results in a spurious
168        # 'java.lang.IndexOutOfBoundsException' - retry a couple of times, if so
169        attempt = 0
170        results = None
171        while results is None:
172            try:
173                results = dr.search(term,
174                            start=1,
175                            howmany=10000, # NB, we want to get back everything!
176                            target=ndg_eXist.ATOM_TARGET,
177                            providerID = providerID, 
178                            atomTypeID = atomTypeID)
179            except xmlrpclib.Fault, e:
180                logging.info("Error caught whilst calling eXist: %s" %e.faultString)
181                attempt += 1
182                if attempt < 3:
183                    logging.info("- retrying eXist call")
184                else:
185                    raise e
186
187        logging.info("Search completed")
188        return results
189
190           
191       
Note: See TracBrowser for help on using the repository browser.