source: MILK/trunk/milk_server/milk_server/controllers/browse/retrieve.py @ 4992

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

Adjust code to fit with changes to ndgCommon codebase + tidy up
structure of ndgInterface to make easier to follow + add documentation
+ add universal debug mode + various other small code tidy ups.

Line 
1'''
2 Class representing pylons controller for the retrieval of metadata records - and
3 records associated with these
4 
5 @author: B Lawrence?, C Byrom, Tessella Sep 2008
6'''
7import logging
8from paste.request import parse_querystring
9from xml.parsers.expat import ExpatError
10from milk_server.lib.base import *
11from milk_server.lib import Utilities
12from milk_server.lib.ndgInterface import ndgInterface
13from ndg.common.src.lib.ETxmlView import et2html
14from ndg.common.src.models import stubB, DIF, ndgObject
15from ndg.common.src.models.ndgObject import ndgObject
16from ndg.common.src.models.Atom import Atom
17from ndg.common.src.models.vocabtermdata import VocabTermData as VTD
18from ndg.common.src.clients.xmldb.eXist.searchclient import SearchClient
19
20class RetrieveController(BaseController):
21    '''
22    Provides the pylons controller for retrieving NDG documents. The simple model
23    is now that an attempt to retrieve/uri will parse the uri, read the config file,
24    and if the local server name is not the same as the uri server name, attempt
25    to retrieve the doc remotely.
26    '''
27   
28    def __setup(self,uri):
29        ''' Common setup stuff for all the actions on this controller '''
30        logging.info("Setting up RetrieveController")
31        self.cf=request.environ['ndgConfig']
32        try:
33            self.uri=ndgObject(uri, config=self.cf)
34        except ValueError,e:
35            return e
36
37        self.inputs=dict(parse_querystring(request.environ))
38
39        # NB: we could have two types of query string argument:
40        #   format= (raw,html) and
41        #   outputSchema=(original, someSchema)
42        self.format=''
43        if 'format' in self.inputs: 
44            self.format=self.inputs['format']
45        self.outputSchema=''
46        if 'outputSchema' in self.inputs: 
47            self.outputSchema=self.inputs['outputSchema']
48                             
49        logging.info("RetrieveController set up")
50        return 0
51       
52    def index(self,uri):
53        ''' Returns the document unadorned in anyway, i.e. the raw xml'''
54        status=self.__setup(uri)
55        if status:
56            c.xml='<p>%s</p>'%status
57            response.status_code = 400
58            return render('error')
59       
60        interface = ndgInterface()
61        status,x = interface.GetXML(uri,outputSchema=self.outputSchema)
62        c.xml = x
63        if status:
64            response.headers['Content-Type'] = 'application/xml'
65            response.write(c.xml)
66        else:
67            e=404
68            if x.startswith('<p> Access'): 
69                e=401
70            response.status_code = e
71            return render('error')
72
73
74    def viewAssociatedData(self, type, uri):
75        '''
76        Get the specified data associated with the uri
77        @param type: type of associated data to lookup - currently VTD.DEPLOYMENT_TERM
78        or VTD.DE_TERM
79        @param uri: valid ndg uri
80        @return rendered genshi deployments template
81        '''
82        logging.info("Getting %s data for '%s'" %(type, uri))
83        status=self.__setup(uri)
84        if status:
85            c.xml='<p>%s</p>'%status
86            response.status_code = 400
87            return render('error')
88
89        try:
90            # NB, we should have stored the current atom data - so look this up now
91            atom = session.get('currentAtom')
92            if atom:
93                c.atom = atom
94            else:
95                interface = ndgInterface()
96                status,x=interface.GetXML(uri,outputSchema=self.outputSchema, useCache=False)
97                c.xmlh=x
98                c.atom = Atom(xmlString=str(x), ndgObject = self.uri)
99           
100            # NB, there are two routes through here - if we're viewing a data entity,
101            # the deployment links are available directly from the atom; if not we
102            # need to look them up
103            lookupIndirectReferences = True
104            if c.atom.isDE():
105                lookupIndirectReferences = False
106           
107            searchClient = SearchClient(dbHostName = self.cf.get('NDG_EXIST','local'),
108                                        configFileName = self.cf.get('NDG_EXIST','passwordFile'))
109           
110            c.atom.lookupAssociatedData(type, searchClient, 
111                                        lookupIndirectReferences = lookupIndirectReferences)
112
113            template = 'atom_editor/deployments_data'
114            if type == VTD.DE_TERM:
115                template = 'atom_editor/data_entities_data'
116
117            # store the atom to retain the looked up info
118            session['currentAtom'] = c.atom
119            session.save()
120               
121            logging.info("- %s data retrieved - now rendering" %type)
122            return render('genshi', template)
123       
124        except ExpatError, e:
125            c.xml='XML content is not well formed'
126            c.doc=str(x)
127            response.status_code = 400
128            logging.error("Error retrieving [%s] - XML content: %s" % (uri, e))
129            return render('error')
130
131        except Exception, e:
132            #we may be showing an xml document ... but it could go wrong if
133            #we have crap content ...
134            c.xml='Unexpected error [%s] viewing [%s]'%(str(e), uri)
135            c.doc=''
136            response.status_code = 400
137            logging.error(c.xml)
138            return render('error')
139
140       
141    def view(self,uri):
142        ''' Returns either an html marked up version of the xml, or a properly laid
143        out version of the document '''
144        c.doc=None
145        # NB, this sets up self.uri as an ndgObject
146        status=self.__setup(uri)
147        if status:
148            c.xml='<p>%s</p>'%status
149            response.status_code = 400
150            return render('error')
151
152        logging.info("Retrieving document to view")
153        useCache = True
154        viewFormat=self.uri.schema
155        # NB, don't use cache if we're looking up atoms as these can change quickly
156        # when using the atom editor
157        if viewFormat == ndgObject.ATOM_DOC_TYPE or \
158            viewFormat ==  ndgObject.ATOM_BACKUP_DOC_TYPE:
159            useCache = False
160           
161        interface = ndgInterface()
162        #(the return object x is an ET object)
163        status,x=interface.GetXML(uri,outputSchema=self.outputSchema, useCache=useCache)
164        c.title='Viewing [%s]'%self.uri
165       
166        # NB, legacy code uses kid templates - newer stuff should use genshi
167        templateType = "kid"
168        if status:
169            logging.debug("Document retrieved ok - now processing results")
170
171            if self.outputSchema!='': 
172                viewFormat=self.outputSchema
173
174            logging.debug("Doc format: %s, View format: %s" \
175                           %(self.format, viewFormat))
176
177            name=str(self.uri)
178            if self.format=='xml':
179                c.xml = et2html(ET.fromstring(x))
180                renderTemplate = 'content'
181                c.tab='Details'
182
183            elif self.format=='raw':
184                c.xml = x
185                response.headers['Content-Type'] = 'application/xml'
186                return response.write(c.xml)
187               
188            elif viewFormat == ndgObject.ATOM_DOC_TYPE or \
189                viewFormat ==  ndgObject.ATOM_BACKUP_DOC_TYPE:
190                renderTemplate = 'atom_editor/atom_editor'
191                c.xmlh = x
192                c.atom = Atom(xmlString=x, ndgObject = self.uri)
193               
194                # get the current publication state
195                edc = Utilities.getExistClient(c.atom.ME.providerID)
196                c.atom.state = edc.getAtomPublicationState(c.atom.datasetID, 
197                                                           c.atom.ME.providerID)
198               
199                c.title = 'Viewing [%s]'%self.uri
200                c.deploymentsURL = h.url_for(controller='browse/retrieve', \
201                                             action='viewAssociatedData', \
202                                             type = VTD.DEPLOYMENT_TERM, \
203                                             uri = self.uri)
204                c.dataEntitiesURL = h.url_for(controller='browse/retrieve', \
205                                             action='viewAssociatedData', \
206                                             type = VTD.DE_TERM, \
207                                             uri = self.uri)
208                templateType = "genshi"
209                # store the atom for easy re-use by asynch calls
210                # - primarily for the viewAssociatedData() method here
211                session['currentAtom'] = c.atom
212                session.save()
213
214            elif viewFormat == ndgObject.MOLES_DOC_TYPE:
215                renderTemplate = 'browse/stubB'
216                c.doc=stubB.stubB(x, self.cf)
217                name=c.doc.abbreviation
218               
219            elif viewFormat == ndgObject.NDGA0_DOC_TYPE:
220                renderTemplate = 'content'
221                name=self.uri.localID
222                #for now we'll handle as pretty print xml
223                c.xml = et2html(x)
224                c.tab='Details'
225               
226            elif viewFormat == ndgObject.DIF_DOC_TYPE or viewFormat == ndgObject.BROWSE_DIF_DOC_TYPE:
227                renderTemplate = 'browse/dif'
228                c.doc=DIF.DIF(x, et=1, ndgObj=self.uri)
229                name=c.doc.name
230               
231            elif viewFormat == ndgObject.NUMSIM_DOC_TYPE:
232                renderTemplate = 'browse/numsim'
233                c.xmlh=x
234                name=x.findtext('NS_Name')
235                c.name=name
236               
237            else:
238                c.xml = et2html(x)
239                renderTemplate = 'content'
240           
241            needed=0
242            if 'lastViewed' not in session: 
243                needed=1
244               
245            session['lastViewed']=h.current_url()
246            if needed: 
247                c.pageTabs.append(('Details',session['lastViewed']))
248           
249            session.save()
250            code=200
251        else:
252            renderTemplate = 'error'
253            if x.startswith('<p> Access Denied'):
254                code=401
255            else: code=400
256            c.xml='%s'%x
257            logging.error(x)
258           
259        response.status_code = code
260        try:
261            return render(templateType, renderTemplate)
262       
263        except ExpatError, e:
264            c.xml='XML content is not well formed'
265            c.doc=str(x)
266            response.status_code = 400
267            logging.error("Error retrieving [%s] - XML content: %s" % (uri, e))
268            return render('error')
269
270        except Exception, e:
271            #we may be showing an xml document ... but it could go wrong if
272            #we have crap content ...
273            c.xml='Unexpected error [%s] viewing [%s]'%(str(e), uri)
274            c.doc=''
275            response.status_code = 400
276            logging.error(c.xml)
277            return render('error')
Note: See TracBrowser for help on using the repository browser.