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

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

A few small fixes to support usage of ndgCommon.

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