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

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

Add two new text area inputs for data entities - to get data on lineage + quality. Also add new help text for these new sections.

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            self.inputs['lineage'] = c.atom.ME.lineage
368            self.inputs['quality'] = c.atom.ME.quality
369            return self.savePageAndRender("atom_editor/atom_editor", **self.inputs)
370       
371        except ExpatError, e:
372            c.xml='XML content is not well formed'
373            c.doc=str(e)
374            logging.error("Error retrieving [%s] - XML content: %s" % (uri, e))
375        except SystemError, e:
376            return self._handleError(e)
377        except Exception, e:
378            errorMessage = traceback.format_exc()
379            c.xml='Unexpected error [%s] viewing [%s]'%(str(e), uri)
380            c.doc=''
381            logging.error(c.xml)
382       
383        response.status_code = 400
384        return render("genshi", 'error')
385
386
387    def addRelatedLinksDropDowns(self):
388        '''
389        Set up the drop down lists required for the selection of online ref links
390        '''
391        # at the very least, we need a simple drop down list with no preselected
392        # values
393        logging.debug("Setting up drop down lists for related links")
394        vtds = g.vtd.getValidTypes(g.vtd.ONLINE_REF_CATEGORY)
395        c.relatedLinkTerms = utils.getVocabTermDataDropdown(vtds)
396
397        # ensure we have set up the correct inputs to allow htmlfill to show
398        # the correct selected value
399        for i, link in enumerate(c.atom.relatedLinks):
400            logging.debug("Adding dropdown for related link, '%s'" %(str(link)))
401            refLabel = Atom.ONLINE_REF_LABEL + "." + str(i) + '.rel'
402           
403            # get the value of the selected list
404            self.__setDropDownSelectVal(refLabel, link.rel, vtds)
405
406        logging.debug("Finished setting up drop down lists")
407
408
409    def extractAuthorDetails(self, inputs):
410        '''
411        Retrieve author data from inputs and set appropriately on Atom, if any
412        found
413        @return: list of Person objects with the author data
414        '''
415        logging.info("Extracting author data from inputs")
416        processedAuthors = []
417        authors = []
418        for key in inputs:
419            keyBits = key.split('.')
420            if len(keyBits) == 3 and keyBits[1] not in processedAuthors:
421               
422                authorType = -1
423                if key.lower().startswith('author'):
424                    authorType = Person.AUTHOR_TYPE
425                elif key.lower().startswith('contributor'):
426                    authorType = Person.CONTRIBUTOR_TYPE
427                elif key.lower().startswith('responsible'):
428                    authorType = Person.RESPONSIBLE_PARTY_TYPE
429                else:
430                    continue
431
432                # NB, adding an empty object here is valid as it will clear out
433                # existing entries, potentially
434                author = Person(personType = authorType)
435                # check if the remove checkbox has been set
436                keyStem = ".".join(keyBits[0:2])
437                if inputs.get(keyStem + ".remove"):
438                    logging.info("Removing author data")
439                else:
440                    author.name = inputs.get(keyStem + '.name') or ""
441                    author.uri = inputs.get(keyStem + '.uri') or ""
442                    author.role = inputs.get(keyStem + '.role') or ""
443                   
444                    logging.info("Adding new author info")
445                    logging.debug("Extracted author (type:'%s', name:'%s', uri:'%s', role:'%s')" \
446                                  %(author.type, author.name, author.uri, author.role))
447                authors.append(author)
448                processedAuthors.append(keyBits[1])
449
450        logging.info("Finished extracting author data")
451        return authors
452
453
454    def extractOnlineReferenceDetails(self, inputs):
455        '''
456        Retrieve online reference data from inputs and set appropriately on Atom, if any
457        found
458        @return: list of Link objects containing the extracted data
459        '''
460        logging.info("Extracting related links data from inputs")
461        processedLinks = []
462        links = []
463
464        for key in inputs:
465            keyBits = key.split('.')
466            if len(keyBits) == 3 and keyBits[1] not in processedLinks:
467               
468                if key.lower().startswith(Atom.ONLINE_REF_LABEL):
469                    link = Link()
470                    keyStem = ".".join(keyBits[0:2])
471                   
472                    if inputs.get(keyStem + ".remove"):
473                        logging.info("Removing online reference data")
474                    else:
475                        # NB, this is in the format vocabURL--termID, so requires further
476                        # processing
477                        link.rel = self.getLatestTermURLFromDropDownInput(inputs.get(keyStem + '.rel'))
478                        link.href = inputs.get(keyStem + '.href') or ""
479                        link.title = inputs.get(keyStem + '.title') or ""
480                       
481                        if not link.hasValue():
482                            continue
483                           
484                        logging.info("Adding new online reference info")
485                        logging.debug("Extracted online reference (href:'%s', title:'%s', rel:'%s')" \
486                                      %(link.href, link.title, link.rel))
487                        links.append(link)
488
489                    processedLinks.append(keyBits[1])
490                else:
491                    continue
492
493        logging.info("Finished extracting links data")
494        return links
495
496
497    def extractParameterDetails(self, inputs):
498        '''
499        Retrieve parameters data from inputs and set appropriately on Atom, if any
500        found
501        @return: list of parameter data in triple string format - i.e.
502        of format, 'label | scheme | term'
503        '''
504        logging.info("Extracting parameters data from inputs")
505        processedParameters = []
506        parameters = []
507
508        emptyParam = " |  | "
509        for key in inputs:
510            keyBits = key.split('.')
511            if len(keyBits) == 3 and keyBits[1] not in processedParameters:
512               
513                if key.lower().startswith(Atom.PARAMETER_LABEL):
514                    keyStem = ".".join(keyBits[0:2])
515                   
516                    if inputs.get(keyStem + ".remove"):
517                        logging.info("Removing parameters data")
518                    else:
519                        parameter = inputs.get(keyStem + '.label') or ""
520                        parameter += " | " + inputs.get(keyStem + '.scheme') or ""
521                        parameter += " | " + inputs.get(keyStem + '.term') or ""
522
523                        if parameter == emptyParam:
524                            continue
525                       
526                        logging.info("Adding new parameter info: %s" %parameter)
527                        parameters.append(parameter)
528
529                    processedParameters.append(keyBits[1])
530                else:
531                    continue
532
533        logging.info("Finished extracting parameters data")
534        return parameters
535
536
537    def extractAtomAssociations(self, inputs):
538        '''
539        Retrieve atom data from inputs and create related links pointing to
540        this data
541        @return: list of Links representing the related atoms
542        '''
543        logging.info("Extracting related atom ID data from inputs")
544        atoms = []
545        processedAtoms = []
546
547        for key in inputs:
548            if key.lower().startswith(Atom.ATOM_REF_LABEL):
549                (x, href, title, rel) = key.split(Atom.DELIMITER)
550                # NB, we handle removes by effectively ignoring them later on
551                if href not in processedAtoms:
552                    processedAtoms.append(href)
553
554                    link = Link()
555                    link.href = href or ""
556                    link.title = title or ""
557                    link.rel = rel or ""
558                   
559                    # adjust href to point to the browse, not the edit version
560                    link.href = link.href.replace('editAtom', 'view')
561                    link.href = link.href.replace(g.server, VTD.BROWSE_SERVER_URL)
562                   
563                    logging.debug("Extracted atom info (href:'%s', title:'%s', rel:'%s')" \
564                                  %(link.href, link.title, link.rel))
565                    atoms.append(link)
566            else:
567                continue
568
569        logging.info("Finished extracting atoms data")
570        return atoms
571               
572
573    def getLatestTermURLFromDropDownInput(self, inputVal):
574        '''
575        Term ID and vocabURL are specified in the drop down menus
576        - using the input from this, return the lastest full href to the
577        term ID
578        '''
579        termData = inputVal.split('--')
580        return g.vtd.getCurrentVocabURI(termData[0]) + \
581                        "/" + termData[1]
582
583
584    def saveAtomToExist(self, atom, newState = None):
585        '''
586        Save the specified atom in eXist
587        @param atom: atom object to save to eXist
588        @keyword newState:  AtomState publication state to move the atom to, default: None
589        - use the current atom state
590        @return atom: atom object saved in eXist
591        '''
592        logging.info("Saving changes to eXist")
593        eXist = Utilities.getExistClient(atom.ME.providerID)
594       
595        if newState and newState != atom.state:
596            createdAtom = eXist.changeAtomPublicationState(atom, newState)
597        else:
598            createdAtom = eXist.createAtom(atom)
599        logging.info("Changes successfully saved to eXist")
600        return createdAtom
601
602   
603    def create(self, saveData = None, **inputs):
604        '''
605        Create a new atom
606        '''
607        self._setup()
608        if saveData:
609            logging.info("Validating input")
610            try:
611                validator = CreateAtomFormSchema()
612                validator.to_python(self.inputs)
613                logging.info("- input valid")
614               
615                logging.info("Creating basic atom")
616                atomTypeID = self.inputs.get('atomTypeID').split('--')[1]
617                self.inputs['atomTypeID'] = atomTypeID
618   
619                # activity deployments should have subtype deployment specified automatically
620                if atomTypeID == g.vtd.ACTIVITY_DEPLOYMENT_TERM:
621                    self.inputs['subtypeID'] = g.vtd.DEPLOYMENT_TERM
622                    self.inputs['atomTypeID'] = g.vtd.ACTIVITY_TERM
623                   
624                self.inputs['providerID'] = self.inputs.get('providerID').split('--')[1]
625                atom = self.saveAtomToExist(Atom(**dict(self.inputs)))
626                url = h.url_for('edit', uri = atom.ndgURI, saveData=None)
627               
628                # NB, the redirect throws an exception, so be careful not to catch it
629                h.redirect_to(url)
630            except Invalid, e:
631                c.errors = e.unpack_errors()
632               
633           
634        logging.info("Setting up atom create template")
635        c.title = CREATE_ATOM_TITLE
636       
637        # set up the drop down content - NB, add special case, 'deployment activity'
638        # - this is just a specialised activity - i.e. with subtype preset
639        c.atomTypes = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.ATOM_CATEGORY))
640        c.providerIDs = utils.getVocabTermDataDropdown(g.vtd.getValidTypes(g.vtd.PROVIDER_CATEGORY))
641
642        try:
643            return self.savePageAndRender('atom_editor/atom_creator', **self.inputs)
644
645        except Exception, e:
646            return self._handleError(e)
647
648   
649    def createGranule(self, **inputs):
650        '''
651        Create a new atom from a granulite file
652        '''
653        self._setup()
654        logging.info("Setting up new atom from granulite template")
655        c.title='Create new data granule atom - from a granulite file'
656
657        if not hasattr(c, 'errors'):
658            c.errors = {}
659        try:
660            return self.savePageAndRender('atom_editor/atom_granulator', **inputs)
661
662        except Exception, e:
663            return self._handleError(e)
Note: See TracBrowser for help on using the repository browser.