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

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

Adjust atom links when in editor mode to point to the editor instance

  • and correct these when saving the data so that the links actually

point to the browse service + turn of granule delete function when not
in edit mode + remove duplicated inclusion of badc icon + tidy up
config file.

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", 'atom_editor/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 = params
215           
216            if self.inputs.get('subtype'):
217                c.atom.subtype = self.getLatestTermURLFromDropDownInput( \
218                        self.inputs.get('subtype'))
219                c.atom.subtypeID = c.atom.subtype.split('/')[-1]
220           
221            if self.inputs.get('publication_state'):
222                newState = AtomState.getAtomState(self.inputs['publication_state'])
223
224        logging.info("Validating input")
225        try:
226            g.validator.setAtom(c.atom)
227            g.validator.validateAtom()
228            logging.info("- input valid")
229           
230            # if a change of state has been specified,
231
232            self.saveAtomToExist(c.atom, newState = newState)
233        except Exception, e:
234            self._unpackErrors(e)
235            logging.info("- input invalid")
236            return self.edit(uri)
237                   
238        # now do redirection - NB, this ensures that current atom contents are
239        # reloaded and displayed
240        h.redirect_to(h.url_for(controller = 'atom_editor/editatom', action='edit', \
241                        uri = c.atom.ndgURI))
242
243
244    def prepareEditForm(self, uri):
245        '''
246        Get everything set up for displaying the edit form
247        @param uri: ndg url for the atom to load in edit mode
248        '''
249        if not c.errors:
250            c.errors = {}
251
252        # NB, can get here directly from saveAtom - if there have been errors
253        # - in this case keep original data
254        if not c.atom:
255            self._setup(uri)
256           
257        c.title= EDIT_TITLE %c.atom.ndgURI
258        c.uri = c.atom.ndgURI
259       
260        c.saveLink = h.url_for('save', saveLevel = self.STANDARD_SAVE, 
261                               uri = c.atom.ndgURI)
262        c.saveAssoc = h.url_for('save', saveLevel = self.REMOVE_ASSOCIATIONS, 
263                                uri = c.atom.ndgURI)
264        c.atom.deploymentsURL = h.url_for('viewAssociatedData', 
265                                          type = VTD.DEPLOYMENT_TERM,
266                                          uri = c.atom.ndgURI)
267        c.atom.dataEntitiesURL = h.url_for('viewAssociatedData', 
268                                           type = VTD.DE_TERM,
269                                           uri = c.atom.ndgURI)
270       
271        # adjust atom type to cope with activity deployment exception
272        atomType = c.atom.atomTypeID
273        if atomType == g.vtd.ACTIVITY_TERM and \
274            c.atom.subtypeID == g.vtd.DEPLOYMENT_TERM:
275            atomType = g.vtd.DEPLOYMENT_TERM
276       
277        c.addEntityLink = h.url_for('list', searchData = '0', \
278                               associatedAtomID = c.atom.ndgURI, \
279                               associatedAtomType = atomType, 
280                               associationType = utils.ENTITY_ASSOCIATION)
281           
282        c.addGranuleLink = h.url_for('list', searchData = '0', \
283                               associatedAtomID = c.atom.ndgURI, \
284                               associatedAtomType = atomType, 
285                               associationType = utils.GRANULE_ASSOCIATION)
286           
287        c.addDeploymentLink = h.url_for('list', searchData = '0', \
288                               associatedAtomID = c.atom.ndgURI, \
289                               associatedAtomType = atomType, 
290                               associationType = utils.DEPLOYMENT_ASSOCIATION)
291
292        # account for special case where we're dealing with deployments
293        listVals = g.vtd.getValidSubTypes(c.atom.atomTypeID)
294        if c.atom.isDeployment():
295            listVals = [g.vtd.TERM_DATA[g.vtd.DEPLOYMENT_TERM]]
296
297        c.subTypes = utils.getVocabTermDataDropdown(listVals, \
298                                        selected=c.atom.subtype)
299       
300        c.states = h.options_for_select(AtomState.selectList, c.atom.state.stateFlag)
301        self.inputs['publication_state'] = c.atom.state.stateFlag
302       
303        self.__setDropDownSelectVal('subtype', c.atom.subtype, listVals)
304        self.addRelatedLinksDropDowns()
305
306
307    def __setDropDownSelectVal(self, name, val, vtds):
308        '''
309        Given a list of vocab terms, with the name of a 'select' tag and the selected
310        value, set the proper value in the inputs dict to allow htmlfill to correctly
311        display the list
312        @param name: name of select element to set the select value of
313        @param val: value of the selected item - NB, this need not be the current vocab
314        term url - but should start with the main stem and end with the termID
315        @param vtds: list of vocab term definition objects
316        '''
317        if not val:
318            return
319        for vtd in vtds:
320            if val.endswith(vtd.termID) and \
321                val.startswith(vtd.vocabURL):
322                self.inputs[name] = utils.getVocabTermDataSelectValue(vtd)
323                return
324           
325
326    def delete(self, uri):
327        '''
328        Delete the atom associated with the specified uri - and return
329        user to the atom home page.  NB, only granule atoms can be deleted
330        at the moment.
331        '''
332        if uri:
333            try:
334                logging.info("Deleting atom, '%s'" %uri)
335                self._setup(uri)
336                eXistClient = Utilities.getExistClient(c.atom.ME.providerID)
337                gran = granulite(None, granuleAtom = c.atom, \
338                                 eXistClient = eXistClient, \
339                                 deleteMode = True)
340   
341                gran.deleteGranuleAndDEReferences()
342                c.deleteResult = "Atom deleted successfully."
343                logging.info("- atom deleted")
344            except Exception, e:
345                logging.error("Problem occured whilst deleting atom: '%s'" %e.message)
346                c.deleteResult = "Warning: a problem occured whilst deleting the atom - this " + \
347                    "may have left the system in an unstable state - please check if the atom, or " + \
348                    "references to the atom still exist"
349
350        return render("genshi", "atom_editor/atom_home")
351       
352   
353    def edit(self, uri):
354        '''
355        Edit the atom with the specified ndg uri
356        '''
357        logging.info("Setting up atom edit template")
358        try:
359            self.prepareEditForm(uri)
360           
361            # NB, there appears to be a bug in htmlfill which automagically
362            # clears out content from textarea - so need to set the content
363            # explicitly for htmlfill to use
364            self.inputs['Content'] = c.atom.Content
365            self.inputs['Summary'] = c.atom.Summary
366            return self.savePageAndRender("atom_editor/atom_editor", **self.inputs)
367       
368        except ExpatError, e:
369            c.xml='XML content is not well formed'
370            c.doc=str(e)
371            logging.error("Error retrieving [%s] - XML content: %s" % (uri, e))
372        except SystemError, e:
373            return self._handleError(e)
374        except Exception, e:
375            errorMessage = traceback.format_exc()
376            c.xml='Unexpected error [%s] viewing [%s]'%(str(e), uri)
377            c.doc=''
378            logging.error(c.xml)
379       
380        response.status_code = 400
381        return render("genshi", 'atom_editor/error')
382
383
384    def addRelatedLinksDropDowns(self):
385        '''
386        Set up the drop down lists required for the selection of online ref links
387        '''
388        # at the very least, we need a simple drop down list with no preselected
389        # values
390        logging.debug("Setting up drop down lists for related links")
391        vtds = g.vtd.getValidTypes(g.vtd.ONLINE_REF_CATEGORY)
392        c.relatedLinkTerms = utils.getVocabTermDataDropdown(vtds)
393
394        # ensure we have set up the correct inputs to allow htmlfill to show
395        # the correct selected value
396        for i, link in enumerate(c.atom.relatedLinks):
397            logging.debug("Adding dropdown for related link, '%s'" %(str(link)))
398            refLabel = Atom.ONLINE_REF_LABEL + "." + str(i) + '.rel'
399           
400            # get the value of the selected list
401            self.__setDropDownSelectVal(refLabel, link.rel, vtds)
402
403        logging.debug("Finished setting up drop down lists")
404
405
406    def extractAuthorDetails(self, inputs):
407        '''
408        Retrieve author data from inputs and set appropriately on Atom, if any
409        found
410        @return: list of Person objects with the author data
411        '''
412        logging.info("Extracting author data from inputs")
413        processedAuthors = []
414        authors = []
415        for key in inputs:
416            keyBits = key.split('.')
417            if len(keyBits) == 3 and keyBits[1] not in processedAuthors:
418               
419                authorType = -1
420                if key.lower().startswith('author'):
421                    authorType = Person.AUTHOR_TYPE
422                elif key.lower().startswith('contributor'):
423                    authorType = Person.CONTRIBUTOR_TYPE
424                elif key.lower().startswith('responsible'):
425                    authorType = Person.RESPONSIBLE_PARTY_TYPE
426                else:
427                    continue
428
429                # NB, adding an empty object here is valid as it will clear out
430                # existing entries, potentially
431                author = Person(personType = authorType)
432                # check if the remove checkbox has been set
433                keyStem = ".".join(keyBits[0:2])
434                if inputs.get(keyStem + ".remove"):
435                    logging.info("Removing author data")
436                else:
437                    author.name = inputs.get(keyStem + '.name') or ""
438                    author.uri = inputs.get(keyStem + '.uri') or ""
439                    author.role = inputs.get(keyStem + '.role') or ""
440                   
441                    logging.info("Adding new author info")
442                    logging.debug("Extracted author (type:'%s', name:'%s', uri:'%s', role:'%s')" \
443                                  %(author.type, author.name, author.uri, author.role))
444                authors.append(author)
445                processedAuthors.append(keyBits[1])
446
447        logging.info("Finished extracting author data")
448        return authors
449
450
451    def extractOnlineReferenceDetails(self, inputs):
452        '''
453        Retrieve online reference data from inputs and set appropriately on Atom, if any
454        found
455        @return: list of Link objects containing the extracted data
456        '''
457        logging.info("Extracting related links data from inputs")
458        processedLinks = []
459        links = []
460
461        for key in inputs:
462            keyBits = key.split('.')
463            if len(keyBits) == 3 and keyBits[1] not in processedLinks:
464               
465                if key.lower().startswith(Atom.ONLINE_REF_LABEL):
466                    link = Link()
467                    keyStem = ".".join(keyBits[0:2])
468                   
469                    if inputs.get(keyStem + ".remove"):
470                        logging.info("Removing online reference data")
471                    else:
472                        # NB, this is in the format vocabURL--termID, so requires further
473                        # processing
474                        link.rel = self.getLatestTermURLFromDropDownInput(inputs.get(keyStem + '.rel'))
475                        link.href = inputs.get(keyStem + '.href') or ""
476                        link.title = inputs.get(keyStem + '.title') or ""
477                       
478                        if not link.hasValue():
479                            continue
480                           
481                        logging.info("Adding new online reference info")
482                        logging.debug("Extracted online reference (href:'%s', title:'%s', rel:'%s')" \
483                                      %(link.href, link.title, link.rel))
484                        links.append(link)
485
486                    processedLinks.append(keyBits[1])
487                else:
488                    continue
489
490        logging.info("Finished extracting links data")
491        return links
492
493
494    def extractParameterDetails(self, inputs):
495        '''
496        Retrieve parameters data from inputs and set appropriately on Atom, if any
497        found
498        @return: list of Category objects containing the extracted data
499        '''
500        logging.info("Extracting parameters data from inputs")
501        processedParameters = []
502        parameters = []
503
504        for key in inputs:
505            keyBits = key.split('.')
506            if len(keyBits) == 3 and keyBits[1] not in processedParameters:
507               
508                if key.lower().startswith(Atom.PARAMETER_LABEL):
509                    parameter = Category()
510                    keyStem = ".".join(keyBits[0:2])
511                   
512                    if inputs.get(keyStem + ".remove"):
513                        logging.info("Removing parameters data")
514                    else:
515                        parameter.term = inputs.get(keyStem + '.term') or ""
516                        parameter.scheme = inputs.get(keyStem + '.scheme') or ""
517                        parameter.label = inputs.get(keyStem + '.label') or ""
518                           
519                        logging.info("Adding new parameter info")
520                        logging.debug("Extracted parameter (vocabURL:'%s', label:'%s', term:'%s')" \
521                                      %(parameter.scheme, parameter.label, parameter.term))
522                        parameters.append(parameter)
523
524                    processedParameters.append(keyBits[1])
525                else:
526                    continue
527
528        logging.info("Finished extracting parameters data")
529        return parameters
530
531
532    def extractAtomAssociations(self, inputs):
533        '''
534        Retrieve atom data from inputs and create related links pointing to
535        this data
536        @return: list of Links representing the related atoms
537        '''
538        logging.info("Extracting related atom ID data from inputs")
539        atoms = []
540        processedAtoms = []
541
542        for key in inputs:
543            if key.lower().startswith(Atom.ATOM_REF_LABEL):
544                (x, href, title, rel) = key.split(Atom.DELIMITER)
545                # NB, we handle removes by effectively ignoring them later on
546                if href not in processedAtoms:
547                    processedAtoms.append(href)
548
549                    link = Link()
550                    link.href = href or ""
551                    link.title = title or ""
552                    link.rel = rel or ""
553                   
554                    # adjust href to point to the browse, not the edit version
555                    link.href = link.href.replace('editAtom', 'view')
556                    link.href = link.href.replace(g.server, VTD.BROWSE_SERVER_URL)
557                   
558                    logging.debug("Extracted atom info (href:'%s', title:'%s', rel:'%s')" \
559                                  %(link.href, link.title, link.rel))
560                    atoms.append(link)
561            else:
562                continue
563
564        logging.info("Finished extracting atoms data")
565        return atoms
566               
567
568    def getLatestTermURLFromDropDownInput(self, inputVal):
569        '''
570        Term ID and vocabURL are specified in the drop down menus
571        - using the input from this, return the lastest full href to the
572        term ID
573        '''
574        termData = inputVal.split('--')
575        return g.vtd.getCurrentVocabURI(termData[0]) + \
576                        "/" + termData[1]
577
578
579    def saveAtomToExist(self, atom, newState = None):
580        '''
581        Save the specified atom in eXist
582        @param atom: atom object to save to eXist
583        @keyword newState:  AtomState publication state to move the atom to, default: None
584        - use the current atom state
585        @return atom: atom object saved in eXist
586        '''
587        logging.info("Saving changes to eXist")
588        eXist = Utilities.getExistClient(atom.ME.providerID)
589       
590        if newState and newState != atom.state:
591            createdAtom = eXist.changeAtomPublicationState(atom, newState)
592        else:
593            createdAtom = eXist.createAtom(atom)
594        logging.info("Changes successfully saved to eXist")
595        return createdAtom
596
597   
598    def create(self, saveData = None, **inputs):
599        '''
600        Create a new atom
601        '''
602        self._setup()
603        if saveData:
604            logging.info("Validating input")
605            try:
606                validator = CreateAtomFormSchema()
607                validator.to_python(self.inputs)
608                logging.info("- input valid")
609               
610                logging.info("Creating basic atom")
611                atomTypeID = self.inputs.get('atomTypeID').split('--')[1]
612                self.inputs['atomTypeID'] = atomTypeID
613   
614                # activity deployments should have subtype deployment specified automatically
615                if atomTypeID == g.vtd.ACTIVITY_DEPLOYMENT_TERM:
616                    self.inputs['subtypeID'] = g.vtd.DEPLOYMENT_TERM
617                    self.inputs['atomTypeID'] = g.vtd.ACTIVITY_TERM
618                   
619                self.inputs['providerID'] = self.inputs.get('providerID').split('--')[1]
620                atom = self.saveAtomToExist(Atom(**dict(self.inputs)))
621                url = h.url_for('edit', uri = atom.ndgURI, saveData=None)
622               
623                # NB, the redirect throws an exception, so be careful not to catch it
624                h.redirect_to(url)
625            except Invalid, e:
626                c.errors = e.unpack_errors()
627               
628           
629        logging.info("Setting up atom create template")
630        c.title = CREATE_ATOM_TITLE
631       
632        # set up the drop down content - NB, add special case, 'deployment activity'
633        # - this is just a specialised activity - i.e. with subtype preset
634        c.atomTypes = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.ATOM_CATEGORY))
635        c.providerIDs = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.PROVIDER_CATEGORY))
636
637        try:
638            return self.savePageAndRender('atom_editor/atom_creator', **self.inputs)
639
640        except Exception, e:
641            return self._handleError(e)
642
643   
644    def createGranule(self, **inputs):
645        '''
646        Create a new atom from a granulite file
647        '''
648        self._setup()
649        logging.info("Setting up new atom from granulite template")
650        c.title='Create new data granule atom - from a granulite file'
651
652        if not hasattr(c, 'errors'):
653            c.errors = {}
654        try:
655            return self.savePageAndRender('atom_editor/atom_granulator', **inputs)
656
657        except Exception, e:
658            return self._handleError(e)
Note: See TracBrowser for help on using the repository browser.