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

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

Generalise existing methods to allow data entities to be looked up with
the same code as associated deployments data + add new templates to
display the DEs + extend the javascript to allow multiple callbacks
to retrieve the info + various tidy ups and fixes.

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