source: MILK/trunk/milk_server/milk_server/controllers/atom_editor/editatom.py @ 5158

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

Add new home page for the browse service + implement usage of the
before methods on controllers to check if MILK is set up to
allow the various services before the controller methods are invoked.
Also add a top level default controller to redirect user to the correct
home page depending on the mode of operation + improve styles,
remove unused controller and move error template to more general top
level - for re-use across the MILK stack.

Line 
1'''
2 Class representing pylons controller for the creation and editing of atom
3 data
4 
5 @author: C Byrom, Tessella Sep 2008
6'''
7import logging, traceback, sys, cgi
8from xml.parsers.expat import ExpatError
9from formencode import Invalid
10from genshi.filters import HTMLFormFiller
11from genshi import HTML
12from milk_server.lib.base import *
13from milk_server.models.form import *
14import ndg.common.src.lib.htmlUtilities as utils
15from ndg.common.src.models.Atom import Atom, Person, Link, Category
16from ndg.common.src.models import AtomState
17from ndg.common.src.lib.atomvalidator import ValidationError
18import ndg.common.src.clients.xmldb.abstractxmldbatomclient as ac
19from ndg.common.src.models.MolesEntity import MolesEntity as ME
20from ndg.common.src.lib.utilities import escapeSpecialCharacters
21from ndg.common.src.models.vocabtermdata import VocabTermData as VTD
22from ndg.common.src.lib.granulite import granulite
23from editorconstants import *
24from atomeditorcontroller import AtomEditorController
25from milk_server.lib import Utilities
26
27class EditatomController(AtomEditorController):
28    '''
29    Provides the pylons controller for editing NDG Atom documents.
30    '''
31    def upload(self, uri):
32        '''
33        Upload a CSML, CDML or granulite file and store it in the session variable
34        NB, if the uri is specified, we're already dealing with an atom
35        (which this refers to) - so the file is not a granulite - since
36        this is used to create an atom from scratch
37        '''
38        logging.info("Uploading file...")
39        self._setup(uri=uri)
40       
41        granFile = request.POST.get('upload_granulite')
42        csmlOrCdmlFile = request.POST.get('CSMLOrCDML')
43       
44        # check whether we can replace existing atoms
45        replaceAtom = self.inputs.get('replaceAtom')
46       
47        # NB, need to turn from string to boolean - there doesn't seem a reliable
48        # way of doing this using built in methods - so just do simple check
49        if replaceAtom == 'True':
50            replaceAtom = True
51        else:
52            replaceAtom = False
53       
54        # if this is true, then re-extract the inputs from the session data
55        if replaceAtom:
56            if session.get(GRAN_FILE_VALUE):
57                granFile = cgi.FieldStorage()
58                granFile.value = session.get(GRAN_FILE_VALUE)
59                granFile.filename = session.get(GRAN_FILE_NAME)
60                del session[GRAN_FILE_VALUE]
61                del session[GRAN_FILE_NAME]
62               
63            if session.get(CSML_OR_CDML_FILE_VALUE):
64                csmlOrCdmlFile = cgi.FieldStorage()
65                csmlOrCdmlFile.value = session.get(CSML_OR_CDML_FILE_VALUE)
66                csmlOrCdmlFile.filename = session.get(CSML_OR_CDML_FILE_NAME)
67                del session[CSML_OR_CDML_FILE_VALUE]
68                del session[CSML_OR_CDML_FILE_NAME]
69         
70        c.errors = {}
71        try:
72            logging.info("Validating inputs")
73            validator = LoadGranuliteFormSchema()
74            validator.to_python(self.inputs)
75            logging.info("- inputs valid")
76           
77            useCSMLID = True
78            if uri:
79                useCSMLID = False
80
81            if (granFile == '' or granFile == None) and \
82                (csmlOrCdmlFile == '' or csmlOrCdmlFile == None):
83                errorMessage = "Error: could not load file - please try again"
84                logging.error(errorMessage)
85                raise IOError(errorMessage)
86            else:
87                # Prepare the basic data model
88                # NB, if loading a granulite, this will create the displayed atom
89                # with the ID taken from the CSML file, if specified
90                fileContents = None
91                if (granFile is not None and granFile != ''):
92                    fileContents = granFile.value
93                   
94                # use the granulite helper class to add either the full granulite
95                # data or just the CSML/CDML data
96                # NB, we'll be creating the atom in the default local eXist
97                eXistClient = Utilities.getExistClient('local')
98                gran = granulite(fileContents, granuleAtom = c.atom, \
99                                 eXistClient = eXistClient, \
100                                 csmlOrCdmlFile = csmlOrCdmlFile, \
101                                 timeAxis = self.inputs.get('timeAxis'), \
102                                 datasetID = self.inputs.get('granuleDatasetID'), \
103                                 useCSMLID = useCSMLID, \
104                                 replaceAtom = replaceAtom)
105
106                # now process the input file and add any extra required data
107                if uri:
108                    c.atom = gran.processCSMLOrCDMLFile()
109
110                    # save new data - NB, for granulites, this is done as part of the
111                    # processing steps
112                    self.saveAtomToExist(c.atom)
113                else:
114                    try:
115                        c.atom = gran.processGranulite()
116
117                        # Now set up the ndgObject with the created atom's vals
118                        self._setup(uri=c.atom.ndgURI, loadAtom = False)
119                        c.atom.ndgObject = self.ndgObject
120                    except ac.DuplicateError, e:
121                        # we've found an existing atom with the same ID
122                        # - give the users the choice of replacing the contents of this atom
123                        # or just exiting
124                        # - NB, do this via a session variable to act as a flag
125                        # for a javascript command
126                        session[OVERWRITE_GRANULE_FLAG] = e.message
127                       
128                        # store the inputs data for easy retrieval
129                        # - NB, file fields don't behave as text fields - for security
130                        # purposes - so need to store their data as session variables
131                        # for easy retrieval
132                        # - Also, cannot pickle the cgi.FieldStorage object so extract
133                        # picklable data and recreate on the return run
134                        if granFile != '':
135                            session[GRAN_FILE_VALUE] = granFile.value
136                            session[GRAN_FILE_NAME] = granFile.filename
137                        if csmlOrCdmlFile != '':
138                            session[CSML_OR_CDML_FILE_VALUE] = csmlOrCdmlFile.value
139                            session[CSML_OR_CDML_FILE_NAME] = csmlOrCdmlFile.filename
140                       
141                        # need to return to original screen - so clear out variables
142                        c.atom = None
143                        uri = None
144                           
145                # now do redirection - NB, this ensures that current atom contents are
146                # reloaded and displayed
147                logging.info("File data loaded and extracted to atom")
148        except Invalid, e:
149            logging.info(" - inputs invalid")
150            c.errors = e.unpack_errors()
151        except ValidationError, e:
152            logging.info(e)
153            self._unpackErrors(e)
154           
155        except Exception, e:
156            c.errors['WARNING'] = ['Error loading data: the displayed data will not be saved - please fix problem and retry']
157            self._unpackErrors(e)
158        except SystemExit, ee:
159            # NB, some of the CSML libraries just sys.exit on problems - catch errors here
160            c.errors['ERROR'] = ['Problem encountered whilst transforming the CDML data into CSML']
161            self._unpackErrors(ee)
162
163        if c.atom and hasattr(c.atom, 'ndgURI'):
164            self.pathInfo = self.pathInfo.replace('upload', 'editAtom')
165
166            # NB, if there are errors, don't redirect otherwise these will get lost
167            if not c.errors:
168                h.redirect_to(h.url_for('edit', uri = c.atom.ndgURI))
169            else:
170                c.atom.contentFile = None
171                return self.edit(c.atom.ndgURI)
172                           
173        elif uri:
174            # something has gone wrong here...
175            return render("genshi", 'error')
176        else:
177            return self.createGranule(**self.inputs)
178
179   
180    def saveAtom(self, uri, saveLevel=0):
181        '''
182        Save the atom contents - NB, validation is done by method decoration
183        - if this fails, the action is reran as a GET with htmlfill auto-populating
184        the fields to keep them as they were before the submission
185        '''
186        logging.info("Saving input atom data")
187        c.errors = {}
188        try:
189            self._setup(uri)
190        except Exception, e:
191            return self._handleError(e)
192       
193        # variable to hold publication state changes
194        newState = None
195       
196        # save atom association changes
197        if int(saveLevel) == self.ADD_ASSOCIATIONS:
198            atomLinks = self.extractAtomAssociations(self.inputs)
199            c.atom.addUniqueRelatedLinks(atomLinks)
200        elif int(saveLevel) == self.REMOVE_ASSOCIATIONS:
201            atomLinks = self.extractAtomAssociations(self.inputs)
202            c.atom.removeRelatedLinks(atomLinks)
203        else:
204            authors = self.extractAuthorDetails(self.inputs)
205            c.atom.addAuthors(authors)
206   
207            onlineRefs = self.extractOnlineReferenceDetails(self.inputs)
208            c.atom.addOnlineReferences(onlineRefs)
209
210            params = self.extractParameterDetails(self.inputs)
211            # NB, the atom type and subtype are added to the categories when the
212            # atom is exported to XML - so don't need to worry about overwriting
213            # them now
214            c.atom.parameters = []
215            c.atom.addParameters(params)
216           
217            if self.inputs.get('subtype'):
218                c.atom.subtype = self.getLatestTermURLFromDropDownInput( \
219                        self.inputs.get('subtype'))
220                c.atom.subtypeID = c.atom.subtype.split('/')[-1]
221           
222            if self.inputs.get('publication_state'):
223                newState = AtomState.getAtomState(self.inputs['publication_state'])
224
225        logging.info("Validating input")
226        try:
227            g.validator.setAtom(c.atom)
228            g.validator.validateAtom()
229            logging.info("- input valid")
230           
231            # if a change of state has been specified,
232
233            self.saveAtomToExist(c.atom, newState = newState)
234        except Exception, e:
235            self._unpackErrors(e)
236            logging.info("- input invalid")
237            return self.edit(uri)
238                   
239        # now do redirection - NB, this ensures that current atom contents are
240        # reloaded and displayed
241        h.redirect_to(h.url_for(controller = 'atom_editor/editatom', action='edit', \
242                        uri = c.atom.ndgURI))
243
244
245    def prepareEditForm(self, uri):
246        '''
247        Get everything set up for displaying the edit form
248        @param uri: ndg url for the atom to load in edit mode
249        '''
250        if not c.errors:
251            c.errors = {}
252
253        # NB, can get here directly from saveAtom - if there have been errors
254        # - in this case keep original data
255        if not c.atom:
256            self._setup(uri)
257           
258        c.title= EDIT_TITLE %c.atom.ndgURI
259        c.uri = c.atom.ndgURI
260       
261        c.saveLink = h.url_for('save', saveLevel = self.STANDARD_SAVE, 
262                               uri = c.atom.ndgURI)
263        c.saveAssoc = h.url_for('save', saveLevel = self.REMOVE_ASSOCIATIONS, 
264                                uri = c.atom.ndgURI)
265        c.atom.deploymentsURL = h.url_for('viewAssociatedData', 
266                                          type = VTD.DEPLOYMENT_TERM,
267                                          uri = c.atom.ndgURI)
268        c.atom.dataEntitiesURL = h.url_for('viewAssociatedData', 
269                                           type = VTD.DE_TERM,
270                                           uri = c.atom.ndgURI)
271       
272        # adjust atom type to cope with activity deployment exception
273        atomType = c.atom.atomTypeID
274        if atomType == g.vtd.ACTIVITY_TERM and \
275            c.atom.subtypeID == g.vtd.DEPLOYMENT_TERM:
276            atomType = g.vtd.DEPLOYMENT_TERM
277       
278        c.addEntityLink = h.url_for('list', searchData = '0', \
279                               associatedAtomID = c.atom.ndgURI, \
280                               associatedAtomType = atomType, 
281                               associationType = utils.ENTITY_ASSOCIATION)
282           
283        c.addGranuleLink = h.url_for('list', searchData = '0', \
284                               associatedAtomID = c.atom.ndgURI, \
285                               associatedAtomType = atomType, 
286                               associationType = utils.GRANULE_ASSOCIATION)
287           
288        c.addDeploymentLink = h.url_for('list', searchData = '0', \
289                               associatedAtomID = c.atom.ndgURI, \
290                               associatedAtomType = atomType, 
291                               associationType = utils.DEPLOYMENT_ASSOCIATION)
292
293        # account for special case where we're dealing with deployments
294        listVals = g.vtd.getValidSubTypes(c.atom.atomTypeID)
295        if c.atom.isDeployment():
296            listVals = [g.vtd.TERM_DATA[g.vtd.DEPLOYMENT_TERM]]
297
298        c.subTypes = utils.getVocabTermDataDropdown(listVals, \
299                                        selected=c.atom.subtype)
300       
301        c.states = h.options_for_select(AtomState.selectList, c.atom.state.stateFlag)
302        self.inputs['publication_state'] = c.atom.state.stateFlag
303       
304        self.__setDropDownSelectVal('subtype', c.atom.subtype, listVals)
305        self.addRelatedLinksDropDowns()
306
307
308    def __setDropDownSelectVal(self, name, val, vtds):
309        '''
310        Given a list of vocab terms, with the name of a 'select' tag and the selected
311        value, set the proper value in the inputs dict to allow htmlfill to correctly
312        display the list
313        @param name: name of select element to set the select value of
314        @param val: value of the selected item - NB, this need not be the current vocab
315        term url - but should start with the main stem and end with the termID
316        @param vtds: list of vocab term definition objects
317        '''
318        if not val:
319            return
320        for vtd in vtds:
321            if val.endswith(vtd.termID) and \
322                val.startswith(vtd.vocabURL):
323                self.inputs[name] = utils.getVocabTermDataSelectValue(vtd)
324                return
325           
326
327    def delete(self, uri):
328        '''
329        Delete the atom associated with the specified uri - and return
330        user to the atom home page.  NB, only granule atoms can be deleted
331        at the moment.
332        '''
333        if uri:
334            try:
335                logging.info("Deleting atom, '%s'" %uri)
336                self._setup(uri)
337                eXistClient = Utilities.getExistClient(c.atom.ME.providerID)
338                gran = granulite(None, granuleAtom = c.atom, \
339                                 eXistClient = eXistClient, \
340                                 deleteMode = True)
341   
342                gran.deleteGranuleAndDEReferences()
343                c.deleteResult = "Atom deleted successfully."
344                logging.info("- atom deleted")
345            except Exception, e:
346                logging.error("Problem occured whilst deleting atom: '%s'" %e.message)
347                c.deleteResult = "Warning: a problem occured whilst deleting the atom - this " + \
348                    "may have left the system in an unstable state - please check if the atom, or " + \
349                    "references to the atom still exist"
350
351        return render("genshi", "atom_editor/atom_home")
352       
353   
354    def edit(self, uri):
355        '''
356        Edit the atom with the specified ndg uri
357        '''
358        logging.info("Setting up atom edit template")
359        try:
360            self.prepareEditForm(uri)
361           
362            # NB, there appears to be a bug in htmlfill which automagically
363            # clears out content from textarea - so need to set the content
364            # explicitly for htmlfill to use
365            self.inputs['Content'] = c.atom.Content
366            self.inputs['Summary'] = c.atom.Summary
367            return self.savePageAndRender("atom_editor/atom_editor", **self.inputs)
368       
369        except ExpatError, e:
370            c.xml='XML content is not well formed'
371            c.doc=str(e)
372            logging.error("Error retrieving [%s] - XML content: %s" % (uri, e))
373        except SystemError, e:
374            return self._handleError(e)
375        except Exception, e:
376            errorMessage = traceback.format_exc()
377            c.xml='Unexpected error [%s] viewing [%s]'%(str(e), uri)
378            c.doc=''
379            logging.error(c.xml)
380       
381        response.status_code = 400
382        return render("genshi", 'error')
383
384
385    def addRelatedLinksDropDowns(self):
386        '''
387        Set up the drop down lists required for the selection of online ref links
388        '''
389        # at the very least, we need a simple drop down list with no preselected
390        # values
391        logging.debug("Setting up drop down lists for related links")
392        vtds = g.vtd.getValidTypes(g.vtd.ONLINE_REF_CATEGORY)
393        c.relatedLinkTerms = utils.getVocabTermDataDropdown(vtds)
394
395        # ensure we have set up the correct inputs to allow htmlfill to show
396        # the correct selected value
397        for i, link in enumerate(c.atom.relatedLinks):
398            logging.debug("Adding dropdown for related link, '%s'" %(str(link)))
399            refLabel = Atom.ONLINE_REF_LABEL + "." + str(i) + '.rel'
400           
401            # get the value of the selected list
402            self.__setDropDownSelectVal(refLabel, link.rel, vtds)
403
404        logging.debug("Finished setting up drop down lists")
405
406
407    def extractAuthorDetails(self, inputs):
408        '''
409        Retrieve author data from inputs and set appropriately on Atom, if any
410        found
411        @return: list of Person objects with the author data
412        '''
413        logging.info("Extracting author data from inputs")
414        processedAuthors = []
415        authors = []
416        for key in inputs:
417            keyBits = key.split('.')
418            if len(keyBits) == 3 and keyBits[1] not in processedAuthors:
419               
420                authorType = -1
421                if key.lower().startswith('author'):
422                    authorType = Person.AUTHOR_TYPE
423                elif key.lower().startswith('contributor'):
424                    authorType = Person.CONTRIBUTOR_TYPE
425                elif key.lower().startswith('responsible'):
426                    authorType = Person.RESPONSIBLE_PARTY_TYPE
427                else:
428                    continue
429
430                # NB, adding an empty object here is valid as it will clear out
431                # existing entries, potentially
432                author = Person(personType = authorType)
433                # check if the remove checkbox has been set
434                keyStem = ".".join(keyBits[0:2])
435                if inputs.get(keyStem + ".remove"):
436                    logging.info("Removing author data")
437                else:
438                    author.name = inputs.get(keyStem + '.name') or ""
439                    author.uri = inputs.get(keyStem + '.uri') or ""
440                    author.role = inputs.get(keyStem + '.role') or ""
441                   
442                    logging.info("Adding new author info")
443                    logging.debug("Extracted author (type:'%s', name:'%s', uri:'%s', role:'%s')" \
444                                  %(author.type, author.name, author.uri, author.role))
445                authors.append(author)
446                processedAuthors.append(keyBits[1])
447
448        logging.info("Finished extracting author data")
449        return authors
450
451
452    def extractOnlineReferenceDetails(self, inputs):
453        '''
454        Retrieve online reference data from inputs and set appropriately on Atom, if any
455        found
456        @return: list of Link objects containing the extracted data
457        '''
458        logging.info("Extracting related links data from inputs")
459        processedLinks = []
460        links = []
461
462        for key in inputs:
463            keyBits = key.split('.')
464            if len(keyBits) == 3 and keyBits[1] not in processedLinks:
465               
466                if key.lower().startswith(Atom.ONLINE_REF_LABEL):
467                    link = Link()
468                    keyStem = ".".join(keyBits[0:2])
469                   
470                    if inputs.get(keyStem + ".remove"):
471                        logging.info("Removing online reference data")
472                    else:
473                        # NB, this is in the format vocabURL--termID, so requires further
474                        # processing
475                        link.rel = self.getLatestTermURLFromDropDownInput(inputs.get(keyStem + '.rel'))
476                        link.href = inputs.get(keyStem + '.href') or ""
477                        link.title = inputs.get(keyStem + '.title') or ""
478                       
479                        if not link.hasValue():
480                            continue
481                           
482                        logging.info("Adding new online reference info")
483                        logging.debug("Extracted online reference (href:'%s', title:'%s', rel:'%s')" \
484                                      %(link.href, link.title, link.rel))
485                        links.append(link)
486
487                    processedLinks.append(keyBits[1])
488                else:
489                    continue
490
491        logging.info("Finished extracting links data")
492        return links
493
494
495    def extractParameterDetails(self, inputs):
496        '''
497        Retrieve parameters data from inputs and set appropriately on Atom, if any
498        found
499        @return: list of parameter data in triple string format - i.e.
500        of format, 'label | scheme | term'
501        '''
502        logging.info("Extracting parameters data from inputs")
503        processedParameters = []
504        parameters = []
505
506        emptyParam = " |  | "
507        for key in inputs:
508            keyBits = key.split('.')
509            if len(keyBits) == 3 and keyBits[1] not in processedParameters:
510               
511                if key.lower().startswith(Atom.PARAMETER_LABEL):
512                    keyStem = ".".join(keyBits[0:2])
513                   
514                    if inputs.get(keyStem + ".remove"):
515                        logging.info("Removing parameters data")
516                    else:
517                        parameter = inputs.get(keyStem + '.label') or ""
518                        parameter += " | " + inputs.get(keyStem + '.scheme') or ""
519                        parameter += " | " + inputs.get(keyStem + '.term') or ""
520
521                        if parameter == emptyParam:
522                            continue
523                       
524                        logging.info("Adding new parameter info: %s" %parameter)
525                        parameters.append(parameter)
526
527                    processedParameters.append(keyBits[1])
528                else:
529                    continue
530
531        logging.info("Finished extracting parameters data")
532        return parameters
533
534
535    def extractAtomAssociations(self, inputs):
536        '''
537        Retrieve atom data from inputs and create related links pointing to
538        this data
539        @return: list of Links representing the related atoms
540        '''
541        logging.info("Extracting related atom ID data from inputs")
542        atoms = []
543        processedAtoms = []
544
545        for key in inputs:
546            if key.lower().startswith(Atom.ATOM_REF_LABEL):
547                (x, href, title, rel) = key.split(Atom.DELIMITER)
548                # NB, we handle removes by effectively ignoring them later on
549                if href not in processedAtoms:
550                    processedAtoms.append(href)
551
552                    link = Link()
553                    link.href = href or ""
554                    link.title = title or ""
555                    link.rel = rel or ""
556                   
557                    # adjust href to point to the browse, not the edit version
558                    link.href = link.href.replace('editAtom', 'view')
559                    link.href = link.href.replace(g.server, VTD.BROWSE_SERVER_URL)
560                   
561                    logging.debug("Extracted atom info (href:'%s', title:'%s', rel:'%s')" \
562                                  %(link.href, link.title, link.rel))
563                    atoms.append(link)
564            else:
565                continue
566
567        logging.info("Finished extracting atoms data")
568        return atoms
569               
570
571    def getLatestTermURLFromDropDownInput(self, inputVal):
572        '''
573        Term ID and vocabURL are specified in the drop down menus
574        - using the input from this, return the lastest full href to the
575        term ID
576        '''
577        termData = inputVal.split('--')
578        return g.vtd.getCurrentVocabURI(termData[0]) + \
579                        "/" + termData[1]
580
581
582    def saveAtomToExist(self, atom, newState = None):
583        '''
584        Save the specified atom in eXist
585        @param atom: atom object to save to eXist
586        @keyword newState:  AtomState publication state to move the atom to, default: None
587        - use the current atom state
588        @return atom: atom object saved in eXist
589        '''
590        logging.info("Saving changes to eXist")
591        eXist = Utilities.getExistClient(atom.ME.providerID)
592       
593        if newState and newState != atom.state:
594            createdAtom = eXist.changeAtomPublicationState(atom, newState)
595        else:
596            createdAtom = eXist.createAtom(atom)
597        logging.info("Changes successfully saved to eXist")
598        return createdAtom
599
600   
601    def create(self, saveData = None, **inputs):
602        '''
603        Create a new atom
604        '''
605        self._setup()
606        if saveData:
607            logging.info("Validating input")
608            try:
609                validator = CreateAtomFormSchema()
610                validator.to_python(self.inputs)
611                logging.info("- input valid")
612               
613                logging.info("Creating basic atom")
614                atomTypeID = self.inputs.get('atomTypeID').split('--')[1]
615                self.inputs['atomTypeID'] = atomTypeID
616   
617                # activity deployments should have subtype deployment specified automatically
618                if atomTypeID == g.vtd.ACTIVITY_DEPLOYMENT_TERM:
619                    self.inputs['subtypeID'] = g.vtd.DEPLOYMENT_TERM
620                    self.inputs['atomTypeID'] = g.vtd.ACTIVITY_TERM
621                   
622                self.inputs['providerID'] = self.inputs.get('providerID').split('--')[1]
623                atom = self.saveAtomToExist(Atom(**dict(self.inputs)))
624                url = h.url_for('edit', uri = atom.ndgURI, saveData=None)
625               
626                # NB, the redirect throws an exception, so be careful not to catch it
627                h.redirect_to(url)
628            except Invalid, e:
629                c.errors = e.unpack_errors()
630               
631           
632        logging.info("Setting up atom create template")
633        c.title = CREATE_ATOM_TITLE
634       
635        # set up the drop down content - NB, add special case, 'deployment activity'
636        # - this is just a specialised activity - i.e. with subtype preset
637        c.atomTypes = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.ATOM_CATEGORY))
638        c.providerIDs = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.PROVIDER_CATEGORY))
639
640        try:
641            return self.savePageAndRender('atom_editor/atom_creator', **self.inputs)
642
643        except Exception, e:
644            return self._handleError(e)
645
646   
647    def createGranule(self, **inputs):
648        '''
649        Create a new atom from a granulite file
650        '''
651        self._setup()
652        logging.info("Setting up new atom from granulite template")
653        c.title='Create new data granule atom - from a granulite file'
654
655        if not hasattr(c, 'errors'):
656            c.errors = {}
657        try:
658            return self.savePageAndRender('atom_editor/atom_granulator', **inputs)
659
660        except Exception, e:
661            return self._handleError(e)
Note: See TracBrowser for help on using the repository browser.