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

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

Add new controller and routes to allow the retrieval of the atom
feeds for the DIF and Published data.

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 ndg.common.src.models.Atom import Atom
9from ndg.common.src.clients.xmldb.eXist.searchclient import SearchClient
10from ndg.common.src.models.vocabtermdata import VocabTermData as VTD, VocabTermItem as VTI
11from milk_server.lib.base import *
12from editorconstants import *
13import ndg.common.src.lib.htmlUtilities as utils
14import ndg.common.src.clients.xmldb.eXist.dbconstants as dc
15from atomeditorcontroller import AtomEditorController
16   
17class ListatomController(AtomEditorController):
18    '''
19    Provides the pylons controller for listing/searching NDG Atom documents.
20    '''
21    def atomHome(self):
22        '''
23        Render a simple home page for the atom editor
24        '''
25        logging.info("Rendering atom home page")
26        c.title = ATOM_HOME_TITLE
27        return self.savePageAndRender("atom_editor/atom_home")
28
29
30    def showExampleGranulite(self):
31        '''
32        Show an example granulite file
33        '''
34        logging.info("Rendering example granulite file page")
35        c.title = EXAMPLE_GRANULITE_TITLE
36        return self.savePageAndRender("atom_editor/granulite_example")
37
38
39    def showAtomHelp(self):
40        '''
41        Show the help page
42        '''
43        logging.info("Rendering help page")
44        c.title = HELP_PAGE_TITLE
45        return self.savePageAndRender("atom_editor/atom_help")
46   
47   
48    def list(self, searchData=None, associatedAtomID=None, \
49             associatedAtomType=None, associationType=None):
50        '''
51        Provide a simple search interface to the atoms data
52        - display a filter + display any results + if an atomID is
53        provided, allow atoms to be linked to this
54        @keyword searchData: if '1' do a search, if '0' just display search filter
55        @keyword associatedAtomID: the ID of an atom to which other atoms
56        should be linked - via deployments
57        @keyword associatedAtomType: type of atom that the data is being
58        associated with
59        @keyword associationType: type of association to be done - NB, use
60        the constants in htmlUtilities for these
61        '''
62        try:
63            c.searchData = None
64            self._setup()
65            if searchData and int(searchData) > 0:
66                logging.info("Preparing atom search")
67                c.searchData = searchData
68                atomTypeID = self.inputs.get('atomTypeID')
69                providerID = self.inputs.get('providerID')
70                # NB, avoid page being reloaded in incorrect state - e.g. after
71                # browser reload
72                if not (atomTypeID and providerID):
73                    return self.list()
74                   
75                atomTypeID = atomTypeID.split('--')[1]
76                providerID = providerID.split('--')[1]
77               
78                # if we're dealing with activity deployments, substitute the typeID
79                # for the subType Deployments term
80                if atomTypeID == VTD.ACTIVITY_DEPLOYMENT_TERM:
81                    atomTypeID = VTD.DEPLOYMENT_TERM
82                   
83                c.results = self.searchAtoms(providerID, atomTypeID, self.inputs.get('title'))
84               
85            logging.info("Rendering atom listings page")
86            c.errors = {}
87            c.title = LIST_ATOM_TITLE
88            c.assocAtomType = associatedAtomType
89            c.associateLink = ""
90            if associatedAtomID:
91                c.associateLink = h.url_for('save', uri = associatedAtomID, \
92                                            saveLevel = self.ADD_ASSOCIATIONS)
93            c.searchLink = h.url_for('list', searchData='1', 
94                                     associatedAtomID = associatedAtomID, \
95                                     associatedAtomType = associatedAtomType, \
96                                     associationType = associationType)
97           
98            # set up the drop down content
99            # NB, if we are here whilst doing an association, restrict the filter
100            # appropriately
101            listVals = []
102            defaultVal = None
103            # set up a default 'all' value
104            allVal = VTI(SearchClient.DEFAULT_ALL_VAL, SearchClient.DEFAULT_ALL_VAL)
105            if associationType:
106                val = int(associationType)
107                if val == utils.GRANULE_ASSOCIATION:
108                    c.title += GRANULE_ASSOCIATION_TITLE
109                    listVals = [g.vtd.TERM_DATA[g.vtd.GRANULE_TERM]]
110                elif val == utils.DEPLOYMENT_ASSOCIATION:
111                    c.title += DEPLOYMENTS_ASSOCIATION_TITLE
112                    listVals = [g.vtd.TERM_DATA[g.vtd.DEPLOYMENT_TERM]]
113                elif val == utils.ENTITY_ASSOCIATION:
114                    c.title += DEPLOYMENTS_DATA_ASSOCIATION_TITLE
115                    listVals = g.vtd.getValidTypes(g.vtd.DEPLOYABLE_ATOM_CATEGORY)
116                    defaultVal = allVal
117            else:
118                listVals = g.vtd.getValidTypes(g.vtd.ATOM_CATEGORY)
119                defaultVal = allVal
120           
121            c.atomTypes = utils.getVocabTermDataDropdown(listVals, \
122                                                   defaultVal = defaultVal, \
123                                                   selected = self.inputs.get('atomTypeID'))
124            c.providerIDs = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.PROVIDER_CATEGORY), 
125                                                     defaultVal = allVal, \
126                                                     selected = self.inputs.get('providerID'))
127
128            return self.savePageAndRender('atom_editor/atom_list', **self.inputs)
129
130        except Exception, e:
131            c.xml='Unexpected error loading page [%s]' %str(e)
132            c.doc=''
133            logging.error(c.xml)
134       
135        response.status_code = 400
136        return render("genshi", 'atom_editor/error')
137   
138   
139    def searchAtoms(self, providerID, atomTypeID, term):
140        '''
141        Search for atoms with specified filter info
142        @param providerID: provider ID of atom or 'all' for all
143        @param atomTypeID: type of atom or 'all' for all
144        @param term: text to search for in atom
145        @return array of dicts with info for each doc found in search
146        '''
147        logging.info("Search for atoms with the following filter: \
148            \nProviderID: '%s'\nAtom Type: '%s'\nText in title: '%s'" \
149            %(providerID, atomTypeID, term))
150       
151        searchClient = SearchClient(dbHostName = self.cf.get('NDG_EXIST','local'),
152                                    configFileName = self.cf.get('NDG_EXIST','passwordFile'))
153       
154        # NB, for some reason, the xmlrpc call to eXist sometimes results in a spurious
155        # 'java.lang.IndexOutOfBoundsException' - retry a couple of times, if so
156        attempt = 0
157        results = None
158        while results is None:
159            try:
160                results = searchClient.search(
161                            term,
162                            start=1,
163                            howmany=10000, # NB, we want to get back everything!
164                            target = SearchClient.ATOM_TARGET,
165                            providerID = providerID, 
166                            atomTypeID = atomTypeID,
167                            useChunked = True)
168            except xmlrpclib.Fault, e:
169                logging.info("Error caught whilst calling eXist: %s" %e.faultString)
170                attempt += 1
171                if attempt < 3:
172                    logging.info("- retrying eXist call")
173                else:
174                    raise e
175
176        logging.info("Search completed")
177        return results
178
179
180    def getFeed(self, feedType):
181        '''
182        Retrieve data from the specified feed type
183        @param feedType: type of feed to rertrieve.  Currently supports
184        types, editorconstants.DIF_FEED and editorconstants.PUBLISHED_FEED
185        @raise ValueError: if unrecognised feed type input
186        @return XML doc representing requested feed
187        '''
188        logging.info("Retrieving feed for '%s' data" %feedType)
189       
190        collection = ""
191        if feedType == PUBLISHED_FEED:
192            collection = dc.ATOM_COLLECTION_PATH + dc.PUBLISHED_COLLECTION_PATH
193        elif feedType == DIF_FEED:
194            collection = dc.DIF_COLLECTION_PATH
195        else:
196            raise ValueError("- unrecognised feed type (%s) - currently only support types, '%s' and '%s'"
197                             %(feedType, PUBLISHED_FEED, DIF_FEED))
198           
199       
200        feed, xml = g.validator._atomClient.feedClient.getAtomFeed(collection,
201                                                              proxyServer = g.proxyServer)
202       
203        logging.info("- returning feed")
204        response.headers['Content-Type'] = 'application/xml'
205        response.write(xml)
206       
Note: See TracBrowser for help on using the repository browser.