def metadata(id=None, dn=None): api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': r = rdb.addMetadata(request.data, dn=dn) id = r['uid'] morer = rdb.getRecord('metadata', {'uid': id}, dn=dn) publishEvent('mpo_metadata', onlyone(morer)) elif request.method == 'GET': #Add logic to parse id if comma separated if id: ids = id.strip().split(',') r = {} for id in ids: rs = rdb.getRecord('metadata', {'uid': id}, dn=dn) if len(rs) == 1: r[id] = rs[0] #unpack single element list else: r[id] = [ ] #{'uid':'0','msg':'invalid response','len':len(rs),'resp':rs} if len(ids) == 1: #return just single record if one uid r = rs else: r = r else: r = rdb.getRecord('metadata', request.args, dn=dn) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json')
def ontologyInstance(id=None, dn=None): api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': r = rdb.addOntologyInstance(request.data,dn=dn) elif request.method == 'PUT': r = rdb.modifyOntologyInstance(request.data,dn=dn) elif request.method == 'GET': if id: r = rdb.getRecord('ontology_instances', {'uid':id}, dn=dn ) else: p_uids=request.args.get('parent_uid') if p_uids: p_uids=p_uids.strip().split(',') r={} rargs=request.args.to_dict() #multidict conversion to dict for pid in p_uids: rargs['parent_uid']=pid rs = rdb.getRecord('ontology_instances', rargs, dn=dn ) r[pid]=rs #element list, can have multiple instances if len(p_uids)==1: #return just single record if one uid r=rs else: r = rdb.getRecord('ontology_instances', request.args, dn=dn ) return Response(json.dumps(r,cls=MPOSetEncoder), mimetype='application/json')
def collection(id=None,dn=None): """ Create and add to collections. Supported routes: /collection - GET a list of all (or filtered) collections - POST a new collection /collection/<id> - GET collection information, including list of member UUIDs - DELETE a collection and the associated elements /collection/?element_uid=:uid - GET collections having element member giving by :uid """ api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': print('api post collection',request.data) r = rdb.addCollection(request.data,dn=dn) morer = rdb.getRecord('collection',{'uid':r['uid']},dn=dn) publishEvent('mpo_collection',onlyone(morer)) elif request.method == 'GET': if id: r = rdb.getRecord('collection',{'uid':id}, dn=dn) else: #particular cases #?element_uid if 'element_uid' in request.args: r = rdb.getRecord('collection_elements',{'uid':request.args['element_uid']}, dn=dn) #general searches else: r = rdb.getRecord('collection',request.args, dn=dn) elif request.method == 'DELETE': if id: r = rdb.deleteCollection({'uid':id}, dn=dn ) else: r=[] return Response(json.dumps(r,cls=MPOSetEncoder),mimetype='application/json',status=200)
def ontologyInstance(id=None, dn=None): api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': r = rdb.addOntologyInstance(request.data, dn=dn) elif request.method == 'PUT': r = rdb.modifyOntologyInstance(request.data, dn=dn) elif request.method == 'GET': if id: r = rdb.getRecord('ontology_instances', {'uid': id}, dn=dn) else: p_uids = request.args.get('parent_uid') if p_uids: p_uids = p_uids.strip().split(',') r = {} rargs = request.args.to_dict() #multidict conversion to dict for pid in p_uids: rargs['parent_uid'] = pid rs = rdb.getRecord('ontology_instances', rargs, dn=dn) r[pid] = rs #element list, can have multiple instances if len(p_uids) == 1: #return just single record if one uid r = rs else: r = rdb.getRecord('ontology_instances', request.args, dn=dn) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json')
def getWorkflowElement(wid, uid=None, dn=None): """ /workflow/:wid/dataobject/:uid - GET dataobjects in workflow specified by :wid if :uid supplied, get specific dataobject """ api_version, root_url, root = get_api_version(request.url) if uid: records = rdb.getRecord('dataobject_instance', { 'work_uid': wid, 'uid': uid }, dn=dn) else: records = rdb.getRecord('dataobject_instance', {'work_uid': wid}, dn=dn) for rr in records: do_uid = rr['do_uid'] rr['do_info'] = rdb.getRecord('dataobject', {'uid': do_uid}, dn=dn)[0] r = { 'result': records, 'count': len(records), 'link-requested': request.url, 'status': 'ok' } return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=200)
def activity(id=None, dn=None): istatus=200 api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': r = rdb.addRecord('activity',request.data,dn=dn) id = r['uid'] morer = rdb.getRecord('activity',{'uid':id},dn=dn) publishEvent('mpo_activity',onlyone(morer)) elif request.method == 'GET': if id: ids=id.strip().split(',') r={} for id in ids: rs = rdb.getRecord('activity',{'uid':id},dn=dn) if rs: r[id]=rs else: r[id]=[]#{'uid':'0','msg':'invalid response','len':len(rs),'resp':rs} if len(ids)==1: #return just single record if one uid r=rs else: r = rdb.getRecord('activity',request.args,dn=dn) #if r='[]', later set metadata with number of records if len(r) == 2 : istatus=404 return Response(json.dumps(r,cls=MPOSetEncoder), mimetype='application/json',status=istatus)
def ontologyTerm(id=None, dn=None): ''' Retrieves the record of an ontology term from its <id> or path. valid routes: ontology/term/<id> ontology/term?path=term/term2/termN ''' api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': objs = json.loads(request.data) #allow for ontology terms with null parents if not objs.has_key('parent_uid'): objs['parent_uid']=None # make sure the term doesn't exist already vocab = rdb.getRecord('ontology_terms', {'parent_uid':objs['parent_uid']}, dn=dn ) for x in vocab: if objs['name'] == x['name']: return Response(json.dumps({'uid':x['uid']}),mimetype='application/json') r = rdb.addRecord('ontology_terms',json.dumps(objs),dn=dn) elif request.method == 'DELETE': if id: r = rdb.deleteOntologyTerms({'uid':id}, dn=dn ) else: r = rdb.deleteOntologyTerms(request.args, dn=dn ) else: if id: r = rdb.getRecord('ontology_terms', {'uid':id}, dn=dn ) else: r = rdb.getRecord('ontology_terms', request.args, dn=dn ) return Response(json.dumps(r,cls=MPOSetEncoder),mimetype='application/json',status=200)
def metadata(id=None, dn=None): api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': r = rdb.addMetadata( request.data, dn=dn) id = r['uid'] morer = rdb.getRecord('metadata',{'uid':id},dn=dn) publishEvent('mpo_metadata',onlyone(morer)) elif request.method == 'GET': #Add logic to parse id if comma separated if id: ids=id.strip().split(',') r={} for id in ids: rs = rdb.getRecord('metadata',{'uid':id},dn=dn) if len(rs)==1: r[id]=rs[0] #unpack single element list else: r[id]=[]#{'uid':'0','msg':'invalid response','len':len(rs),'resp':rs} if len(ids)==1: #return just single record if one uid r=rs else: r=r else: r = rdb.getRecord('metadata',request.args,dn=dn) return Response(json.dumps(r,cls=MPOSetEncoder), mimetype='application/json')
def activity(id=None, dn=None): istatus = 200 api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': r = rdb.addRecord('activity', request.data, dn=dn) id = r['uid'] morer = rdb.getRecord('activity', {'uid': id}, dn=dn) publishEvent('mpo_activity', onlyone(morer)) elif request.method == 'GET': if id: ids = id.strip().split(',') r = {} for id in ids: rs = rdb.getRecord('activity', {'uid': id}, dn=dn) if rs: r[id] = rs else: r[id] = [ ] #{'uid':'0','msg':'invalid response','len':len(rs),'resp':rs} if len(ids) == 1: #return just single record if one uid r = rs else: r = rdb.getRecord('activity', request.args, dn=dn) #if r='[]', later set metadata with number of records if len(r) == 2: istatus = 404 return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=istatus)
def getWorkflowElement(wid,uid=None,dn=None): """ /workflow/:wid/dataobject/:uid - GET dataobjects in workflow specified by :wid if :uid supplied, get specific dataobject """ api_version,root_url,root=get_api_version(request.url) if uid: records = rdb.getRecord('dataobject_instance',{'work_uid':wid,'uid':uid}, dn=dn ) else: records = rdb.getRecord('dataobject_instance',{'work_uid':wid}, dn=dn ) for rr in records: do_uid=rr['do_uid'] rr['do_info']=rdb.getRecord('dataobject',{'uid':do_uid}, dn=dn )[0] r={'result':records,'count':len(records),'link-requested':request.url, 'status':'ok'} return Response(json.dumps(r,cls=MPOSetEncoder),mimetype='application/json',status=200)
def comment(id=None, dn=None): api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': req = json.loads(request.data) req['ptype'] = rdb.getRecordTable(req['parent_uid'], dn=dn) r = rdb.addRecord('comment', json.dumps(req), dn=dn) id = r['uid'] if apidebug: print('APIDEBUG comment route:: dn = ', dn) try: #JCW just being careful here on first implementation morer = rdb.getRecord('comment', {'uid': id}, dn=dn) except Exception as e: import sys, os exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print('get comment exception', exc_type, fname, exc_tb.tb_lineno) publishEvent('mpo_comment', onlyone(morer)) elif request.method == 'GET': #Add logic to parse id if comma separated if id: ids = id.strip().split(',') r = {} for id in ids: rs = rdb.getRecord('comment', {'uid': id}, dn=dn) if len(rs) == 1: r[id] = rs[0] #unpack single element list else: r[id] = [ ] #{'uid':'0','msg':'invalid response','len':len(rs),'resp':rs} if len(ids) == 1: #return just single record if one uid r = rs else: r = r else: r = rdb.getRecord('comment', request.args, dn=dn) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json')
def ontologyTerm(id=None, dn=None): ''' Retrieves the record of an ontology term from its <id> or path. valid routes: ontology/term/<id> ontology/term?path=term/term2/termN ''' api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': objs = json.loads(request.data) #allow for ontology terms with null parents if not objs.has_key('parent_uid'): objs['parent_uid'] = None # make sure the term doesn't exist already vocab = rdb.getRecord('ontology_terms', {'parent_uid': objs['parent_uid']}, dn=dn) for x in vocab: if objs['name'] == x['name']: return Response(json.dumps({'uid': x['uid']}), mimetype='application/json') r = rdb.addRecord('ontology_terms', json.dumps(objs), dn=dn) elif request.method == 'DELETE': if id: r = rdb.deleteOntologyTerms({'uid': id}, dn=dn) else: r = rdb.deleteOntologyTerms(request.args, dn=dn) else: if id: r = rdb.getRecord('ontology_terms', {'uid': id}, dn=dn) else: r = rdb.getRecord('ontology_terms', request.args, dn=dn) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=200)
def comment(id=None, dn=None): api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': req = json.loads(request.data) req['ptype']=rdb.getRecordTable(req['parent_uid'], dn=dn) r = rdb.addRecord('comment',json.dumps(req),dn=dn) id = r['uid'] if apidebug: print('APIDEBUG comment route:: dn = ',dn) try: #JCW just being careful here on first implementation morer = rdb.getRecord('comment',{'uid':id},dn=dn) except Exception as e: import sys,os exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print('get comment exception',exc_type, fname, exc_tb.tb_lineno) publishEvent('mpo_comment',onlyone(morer)) elif request.method == 'GET': #Add logic to parse id if comma separated if id: ids=id.strip().split(',') r={} for id in ids: rs = rdb.getRecord('comment',{'uid':id},dn=dn) if len(rs)==1: r[id]=rs[0] #unpack single element list else: r[id]=[]#{'uid':'0','msg':'invalid response','len':len(rs),'resp':rs} if len(ids)==1: #return just single record if one uid r=rs else: r=r else: r = rdb.getRecord('comment',request.args,dn=dn) return Response(json.dumps(r,cls=MPOSetEncoder), mimetype='application/json')
def collection(id=None, dn=None): """ Create and add to collections. Supported routes: /collection - GET a list of all (or filtered) collections - POST a new collection /collection/<id> - GET collection information, including list of member UUIDs - DELETE a collection and the associated elements /collection/?element_uid=:uid - GET collections having element member giving by :uid """ api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': print('api post collection', request.data) r = rdb.addCollection(request.data, dn=dn) morer = rdb.getRecord('collection', {'uid': r['uid']}, dn=dn) publishEvent('mpo_collection', onlyone(morer)) elif request.method == 'GET': if id: r = rdb.getRecord('collection', {'uid': id}, dn=dn) else: #particular cases #?element_uid if 'element_uid' in request.args: r = rdb.getRecord('collection_elements', {'uid': request.args['element_uid']}, dn=dn) #general searches else: r = rdb.getRecord('collection', request.args, dn=dn) elif request.method == 'DELETE': if id: r = rdb.deleteCollection({'uid': id}, dn=dn) else: r = [] return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=200)
def ontologyTermVocabulary(id=None, dn=None): ''' Resource: ontology vocabulary Convenience route, equivalent to ontology/term?parent_uid=<id> This function returns the vocabulary of an ontology term specified by its <id>=parent_id. Vocabulary is defined as the next set of terms below it in the ontology term tree. It is a convenience route equivalent to GET ontology_term?parent_uid=uid ''' api_version,root_url,root=get_api_version(request.url) if not id: id='None' r = rdb.getRecord('ontology_terms', {'parent_uid':id}, dn=dn ) r.append( {'link-requested':request.url} ) return Response(json.dumps(r,cls=MPOSetEncoder),mimetype='application/json',status=200)
def ontologyTermVocabulary(id=None, dn=None): ''' Resource: ontology vocabulary Convenience route, equivalent to ontology/term?parent_uid=<id> This function returns the vocabulary of an ontology term specified by its <id>=parent_id. Vocabulary is defined as the next set of terms below it in the ontology term tree. It is a convenience route equivalent to GET ontology_term?parent_uid=uid ''' api_version, root_url, root = get_api_version(request.url) if not id: id = 'None' r = rdb.getRecord('ontology_terms', {'parent_uid': id}, dn=dn) r.append({'link-requested': request.url}) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=200)
def collectionElement(id=None, oid=None, dn=None): """ /collection/:id/element - GET a list of objects in a collection - POST to add to the collection /collection/:id/element/:oid - GET details of a single object in a collection. Should resolve oid to full record from relevant table. /collection/:id/element?detail=full[sparse] - GET collection information with full details [or default sparse as /collection/<id>] """ api_version,root_url,root=get_api_version(request.url) if request.method == 'POST': payload = json.loads(request.data) #make sure the element hasn't been added to the collection already #elems must be a list of uids that are not already in this collection, if it exists. elems = payload.get('elements') if elems: if not isinstance(elems,list): elements=[elems] else: elements=elems else: elements=[] #remove elements already in the collection for e in elements[:]: r = rdb.getRecord('collection_elements',{'uid':e,'parent_uid':id}, dn=dn) if len(r)!=0: elements.remove(e) #maybe add to response message this was done payload['elements'] = elements #add elements one and a time and create list of returned records r=[] for e in elements: rr=rdb.addRecord('collection_elements',json.dumps({'uid':e,'parent_uid':id}),dn=dn) r.append(rr) morer = rdb.getRecord('collection_elements',{'uid':rr['uid']},dn=dn) publishEvent('mpo_collection_elements',onlyone(morer)) elif request.method == 'DELETE': if oid: r = rdb.deleteCollectionElement({'parent_uid':id,'uid':oid}, dn=None) else: r = [] elif request.method == 'GET': if oid: r = rdb.getRecord('collection_elements',{'parent_uid':id,'uid':oid}, dn=dn) else: r = rdb.getRecord('collection_elements',{'parent_uid':id}, dn=dn) #Find original item and add it to record. for record in r: print ('collection element r',record) r_uid=record['uid'] #getRecordTable returns a python dict record['type']=rdb.getRecordTable( r_uid, dn=dn ) #set default field values detail={'related':'not sure','link-related':root_url,'related':'cousins', 'name':'what is this?','description':'empty','time':'nowhen'} #Translation for specific types if record['type']=='workflow': detail=rdb.getWorkflow({'uid':r_uid},dn=dn)[0] print('element workflow',detail) detail['related']=rdb.getWorkflowCompositeID(r_uid,dn=dn).get('alias') links={} links['link1']=root_url+'/workflow/'+r_uid links['link2']=root_url+'/workflow?alias='+detail['related'] detail['link-related']=links elif record['type']=='dataobject': detail=rdb.getRecord('dataobject',{'uid':r_uid},dn=dn)[0] detail['related']=detail.get('uri') detail['link-related']=root_url+'/dataobject/'+r_uid elif record['type']=='dataobject_instance': do_uid=(rdb.getRecord('dataobject_instance',{'uid':record['uid']},dn=dn)[0]).get('do_uid') detail=rdb.getRecord('dataobject',{'uid':do_uid},dn=dn)[0] detail['related']=detail.get('uri') detail['link-related']=root_url+'/dataobject/'+do_uid elif record['type']=='collection': thisdetail=rdb.getRecord('collection',{'uid':r_uid},dn=dn)[0] detail['related']=None detail['link-related']=root_url+'/collection/'+r_uid+'/element' detail['description']=thisdetail.get('description') detail['name']=thisdetail.get('name') detail['time']=thisdetail.get('time') record['name']=detail['name'] record['description']=detail['description'] record['time']=detail['time'] record['related']=detail['related'] record['link-related']=detail['link-related'] istatus=200 # if len(r) == 0: # #istatus = 404 # r=[{'mesg':'No records found', 'number_of_records':0, 'status':404}] return Response(json.dumps(r,cls=MPOSetEncoder),mimetype='application/json',status=istatus)
def dataobject(id=None, dn=None): """ Route to add data objects and connect their instances to workflows. Route: GET /dataobject/<id> Retrieves information on a specific dataobject. In the case <id> is <id> of an instance, instance inherits properties of the original object. In the case <id> is <id> of an dataobject, just the properties of the dataobject are returned. NOT IMPLEMENTED: ?instance filter will optionally return instances of a specified dataobject. Route: GET /dataobject returns all dataobjects GET /dataobject?instance returns all dataobject instances Route: POST /dataobject databody: {'name':, 'description':,'work_uid':, 'uri':, 'parent_uid':, 'uid': } If 'work_uid' is present, create an instance, connect it to the parent in the workflow and link instance to the dataobject as determined by the 'uri'. If 'work_uid' is NOT present, 'parent_uid' must also not be present. A new dataobject is created. Dataobject instances in workflows can be created by supplying a URI, DO_UID, or DOI_UID. If a doi_uid is given, it is resolved to the parent do_uid. If both URI and UID are provided, the URI takes precedence. """ api_version,root_url,root=get_api_version(request.url) istatus=200 messages={} messages['api_version']=api_version if request.method == 'POST': req = json.loads(request.data) #Make sure name and description are present if req.get('name')==None: req['name']="None given" if req.get('description')==None: req['description']="None given" #find the dataobject with the specified uri (assumed to be unique) #or if no URI given, find it by UID. If not found, we make it. if req.get('uri'): do = rdb.getRecord('dataobject',{'uri':req['uri']},dn=dn) if req.get('uid'): #check if consistent if do[0].get('uid'): if not do[0].get('uid') == req.get('uid'): messages['warning']="\nCaution, dataobject UID does not match record from URI." elif req.get('uid'): #if we get here, there is no URI only perhaps a UID do = rdb.getRecord('dataobject',{'uid':req['uid']},dn=dn) #now remove the uid from the request so it does not get passed to #the dataobject_instance creation popuid=req.pop('uid') else: do = False #If the D.O. exists, point to it, if not, make it and point to it if do: if not (req.get('work_uid') and req.get('parent_uid')): messages['info']='dataobject found. provide both work_uid and parent_uid to attach to a workflow.' do[0]['messages']=messages return Response(json.dumps(do,cls=MPOSetEncoder), mimetype='application/json',status=istatus) else: req['do_uid']=do[0]['uid'] else: do_add = rdb.addRecord('dataobject',request.data,dn=dn) do = rdb.getRecord('dataobject',{'uid':do_add['uid']},dn=dn) #retrieve it to get full record if not (req.get('work_uid') and req.get('parent_uid')): messages['info']='dataobject created. provide both work_uid and parent_uid to attach to a workflow.' do[0]['messages']=messages return Response(json.dumps(do,cls=MPOSetEncoder), mimetype='application/json',status=istatus) else: if apidebug: print('do is ',str(do) ) req['do_uid']=do[0]['uid'] #At this point, we have a dataobject record. Now add it to the workflow since should #also have a work_uid and parent_uid #First check if we already have an instance attached to this parent_uid #we only permit one instance per parent of the same object #We needs something like get dataobject?instance&do_uid=do_uid&work_uid=wid #to get a list of uses in this workflow and then figure out if they have the same parent. #perhaps by using rdb.getWorkflowElements. This is really a topological question - we may #have more of these. #check = rdb.getRecord('dataobject_instance',{'do_uid':id},dn=dn) r = rdb.addRecord('dataobject_instance',json.dumps(req),dn=dn) id = r['uid'] morer = rdb.getRecord('dataobject_instance',{'uid':id},dn=dn) publishEvent('mpo_dataobject',onlyone(morer)) elif request.method == 'GET': #handling for comma separated UIDs if id: ids=id.strip().split(',') r={} for id in ids: rs = rdb.getRecord('dataobject',{'uid':id},dn=dn) if len(rs)==1: rs=rs[0] rs['link-related']='link to get workflows using dataobject' r[id]=rs else: #record was not found, check other route rs = rdb.getRecord('dataobject_instance',{'uid':id},dn=dn) if len(rs)==1: rs=rs[0] #add dataobject fields do_info=rdb.getRecord('dataobject',{'uid':rs.get('do_uid')},dn=dn) rs['do_info']=do_info[0] r[id]=rs else: rs={'uid':'0','msg':'not found'} r[id]=rs if len(ids)==1: #return just single record if one uid r=[rs] #following convention that a list is always returned #Get all records, possibly with filters, support 'instance' flag else: if request.args.has_key('instance'): records = rdb.getRecord('dataobject_instance',request.args,dn=dn) for rr in records: do_uid=rr['do_uid'] rr['do_info']=rdb.getRecord('dataobject',{'uid':do_uid}, dn=dn )[0] r=records else: r = rdb.getRecord('dataobject',request.args,dn=dn) return Response(json.dumps(r,cls=MPOSetEncoder), mimetype='application/json',status=istatus)
def dataobject(id=None, dn=None): """ Route to add data objects and connect their instances to workflows. Route: GET /dataobject/<id> Retrieves information on a specific dataobject. In the case <id> is <id> of an instance, instance inherits properties of the original object. In the case <id> is <id> of an dataobject, just the properties of the dataobject are returned. NOT IMPLEMENTED: ?instance filter will optionally return instances of a specified dataobject. Route: GET /dataobject returns all dataobjects GET /dataobject?instance returns all dataobject instances Route: POST /dataobject databody: {'name':, 'description':,'work_uid':, 'uri':, 'parent_uid':, 'uid': } If 'work_uid' is present, create an instance, connect it to the parent in the workflow and link instance to the dataobject as determined by the 'uri'. If 'work_uid' is NOT present, 'parent_uid' must also not be present. A new dataobject is created. Dataobject instances in workflows can be created by supplying a URI, DO_UID, or DOI_UID. If a doi_uid is given, it is resolved to the parent do_uid. If both URI and UID are provided, the URI takes precedence. """ api_version, root_url, root = get_api_version(request.url) istatus = 200 messages = {} messages['api_version'] = api_version if request.method == 'POST': req = json.loads(request.data) #Make sure name and description are present if req.get('name') == None: req['name'] = "None given" if req.get('description') == None: req['description'] = "None given" #find the dataobject with the specified uri (assumed to be unique) #or if no URI given, find it by UID. If not found, we make it. if req.get('uri'): do = rdb.getRecord('dataobject', {'uri': req['uri']}, dn=dn) if req.get('uid'): #check if consistent if do[0].get('uid'): if not do[0].get('uid') == req.get('uid'): messages[ 'warning'] = "\nCaution, dataobject UID does not match record from URI." elif req.get( 'uid'): #if we get here, there is no URI only perhaps a UID do = rdb.getRecord('dataobject', {'uid': req['uid']}, dn=dn) #now remove the uid from the request so it does not get passed to #the dataobject_instance creation popuid = req.pop('uid') else: do = False #If the D.O. exists, point to it, if not, make it and point to it if do: if not (req.get('work_uid') and req.get('parent_uid')): messages[ 'info'] = 'dataobject found. provide both work_uid and parent_uid to attach to a workflow.' do[0]['messages'] = messages return Response(json.dumps(do, cls=MPOSetEncoder), mimetype='application/json', status=istatus) else: req['do_uid'] = do[0]['uid'] else: do_add = rdb.addRecord('dataobject', request.data, dn=dn) do = rdb.getRecord('dataobject', {'uid': do_add['uid']}, dn=dn) #retrieve it to get full record if not (req.get('work_uid') and req.get('parent_uid')): messages[ 'info'] = 'dataobject created. provide both work_uid and parent_uid to attach to a workflow.' do[0]['messages'] = messages return Response(json.dumps(do, cls=MPOSetEncoder), mimetype='application/json', status=istatus) else: if apidebug: print('do is ', str(do)) req['do_uid'] = do[0]['uid'] #At this point, we have a dataobject record. Now add it to the workflow since should #also have a work_uid and parent_uid #First check if we already have an instance attached to this parent_uid #we only permit one instance per parent of the same object #We needs something like get dataobject?instance&do_uid=do_uid&work_uid=wid #to get a list of uses in this workflow and then figure out if they have the same parent. #perhaps by using rdb.getWorkflowElements. This is really a topological question - we may #have more of these. #check = rdb.getRecord('dataobject_instance',{'do_uid':id},dn=dn) r = rdb.addRecord('dataobject_instance', json.dumps(req), dn=dn) id = r['uid'] morer = rdb.getRecord('dataobject_instance', {'uid': id}, dn=dn) publishEvent('mpo_dataobject', onlyone(morer)) elif request.method == 'GET': #handling for comma separated UIDs if id: ids = id.strip().split(',') r = {} for id in ids: rs = rdb.getRecord('dataobject', {'uid': id}, dn=dn) if len(rs) == 1: rs = rs[0] rs['link-related'] = 'link to get workflows using dataobject' r[id] = rs else: #record was not found, check other route rs = rdb.getRecord('dataobject_instance', {'uid': id}, dn=dn) if len(rs) == 1: rs = rs[0] #add dataobject fields do_info = rdb.getRecord('dataobject', {'uid': rs.get('do_uid')}, dn=dn) rs['do_info'] = do_info[0] r[id] = rs else: rs = {'uid': '0', 'msg': 'not found'} r[id] = rs if len(ids) == 1: #return just single record if one uid r = [rs] #following convention that a list is always returned #Get all records, possibly with filters, support 'instance' flag else: if request.args.has_key('instance'): records = rdb.getRecord('dataobject_instance', request.args, dn=dn) for rr in records: do_uid = rr['do_uid'] rr['do_info'] = rdb.getRecord('dataobject', {'uid': do_uid}, dn=dn)[0] r = records else: r = rdb.getRecord('dataobject', request.args, dn=dn) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=istatus)
def workflow(id=None, dn=None): """ Implementation of the /workflow route Enforces ontological constraints on workflows types retrieved from ontology_terms. /workflow?do_uri=:uri - GET workflows having dataobject member giving by :uid """ #Desperately need to add field error checking. Note, we have access to db.query_map api_version,root_url,root=get_api_version(request.url) if apidebug: print ('APIDEBUG: You are: %s'% str(dn) ) print ('APIDEBUG: workflow url request is %s' %request.url) if request.method == 'POST': #check for valid workflow type wtype = json.loads(request.data).get('type') ont_entry = rdb.getRecord('ontology_terms', {'path':'/Workflow/Type'}, dn )[0] vocab=rdb.getRecord('ontology_terms', {'parent_uid':ont_entry['uid']}, dn ) valid= tuple(x['name'] for x in vocab) if (wtype in valid): ##Add logic to check for fields or exceptions from query type_uid = ont_entry.get('uid') p=json.loads(request.data) payload={"name":p['name'],"description":p['description'],"type_uid":type_uid,"value":wtype} r = rdb.addWorkflow(payload,dn=dn) #should return ENTIRE record created. use rdb.getworkflow internally else: payload={"url":request.url, "body":request.data, "hint":valid, "uid":-1} raise InvalidAPIUsage(message='Invalid workflow type specified',status_code=400, payload=payload) elif request.method == 'GET': if id: darg=dict(request.args.items(multi=True)+[('uid',id)]) if apidebug: print('APIDEBUG: darg is %s' %darg) r = rdb.getWorkflow({'uid':id},dn=dn) else: if 'do_uri' in request.args: #find data object by uri r = rdb.getRecord('dataobject',{'uri':request.args['do_uri']}, dn=dn) if len(r)==1: do_uid=r[0].get('uid') #find dataobject instances based on do_uid doi_list = rdb.getRecord('dataobject_instance',{'do_uid':do_uid}, dn=dn ) result=[] for doi in doi_list: result.append(rdb.getWorkflow({'uid':doi['work_uid']},dn=dn)[0]) r={'result':result,'count':len(result),'link-requested':request.url, 'status':'ok'} else: r={'uid':'0','msg':'not found'} #general searches else: r = rdb.getWorkflow(request.args,dn=dn) #add workflow type here in return. Use complete path? if apidebug: print ('APIDEBUG: workflow returning "%s" len %d'% (r,len(r),)) if apidebug: print ('APIDEBUG: workflow %s'% (r,) ) return Response(json.dumps(r,cls=MPOSetEncoder),mimetype='application/json',status=200)
def workflow(id=None, dn=None): """ Implementation of the /workflow route Enforces ontological constraints on workflows types retrieved from ontology_terms. /workflow?do_uri=:uri - GET workflows having dataobject member giving by :uid """ #Desperately need to add field error checking. Note, we have access to db.query_map api_version, root_url, root = get_api_version(request.url) if apidebug: print('APIDEBUG: You are: %s' % str(dn)) print('APIDEBUG: workflow url request is %s' % request.url) if request.method == 'POST': #check for valid workflow type wtype = json.loads(request.data).get('type') ont_entry = rdb.getRecord('ontology_terms', {'path': '/Workflow/Type'}, dn)[0] vocab = rdb.getRecord('ontology_terms', {'parent_uid': ont_entry['uid']}, dn) valid = tuple(x['name'] for x in vocab) if (wtype in valid): ##Add logic to check for fields or exceptions from query type_uid = ont_entry.get('uid') p = json.loads(request.data) payload = { "name": p['name'], "description": p['description'], "type_uid": type_uid, "value": wtype } r = rdb.addWorkflow(payload, dn=dn) #should return ENTIRE record created. use rdb.getworkflow internally else: payload = { "url": request.url, "body": request.data, "hint": valid, "uid": -1 } raise InvalidAPIUsage(message='Invalid workflow type specified', status_code=400, payload=payload) elif request.method == 'GET': if id: darg = dict(request.args.items(multi=True) + [('uid', id)]) if apidebug: print('APIDEBUG: darg is %s' % darg) r = rdb.getWorkflow({'uid': id}, dn=dn) else: if 'do_uri' in request.args: #find data object by uri r = rdb.getRecord('dataobject', {'uri': request.args['do_uri']}, dn=dn) if len(r) == 1: do_uid = r[0].get('uid') #find dataobject instances based on do_uid doi_list = rdb.getRecord('dataobject_instance', {'do_uid': do_uid}, dn=dn) result = [] for doi in doi_list: result.append( rdb.getWorkflow({'uid': doi['work_uid']}, dn=dn)[0]) r = { 'result': result, 'count': len(result), 'link-requested': request.url, 'status': 'ok' } else: r = {'uid': '0', 'msg': 'not found'} #general searches else: r = rdb.getWorkflow(request.args, dn=dn) #add workflow type here in return. Use complete path? if apidebug: print('APIDEBUG: workflow returning "%s" len %d' % ( r, len(r), )) if apidebug: print('APIDEBUG: workflow %s' % (r, )) return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=200)
def collectionElement(id=None, oid=None, dn=None): """ /collection/:id/element - GET a list of objects in a collection - POST to add to the collection /collection/:id/element/:oid - GET details of a single object in a collection. Should resolve oid to full record from relevant table. /collection/:id/element?detail=full[sparse] - GET collection information with full details [or default sparse as /collection/<id>] """ api_version, root_url, root = get_api_version(request.url) if request.method == 'POST': payload = json.loads(request.data) #make sure the element hasn't been added to the collection already #elems must be a list of uids that are not already in this collection, if it exists. elems = payload.get('elements') if elems: if not isinstance(elems, list): elements = [elems] else: elements = elems else: elements = [] #remove elements already in the collection for e in elements[:]: r = rdb.getRecord('collection_elements', { 'uid': e, 'parent_uid': id }, dn=dn) if len(r) != 0: elements.remove( e) #maybe add to response message this was done payload['elements'] = elements #add elements one and a time and create list of returned records r = [] for e in elements: rr = rdb.addRecord('collection_elements', json.dumps({ 'uid': e, 'parent_uid': id }), dn=dn) r.append(rr) morer = rdb.getRecord('collection_elements', {'uid': rr['uid']}, dn=dn) publishEvent('mpo_collection_elements', onlyone(morer)) elif request.method == 'DELETE': if oid: r = rdb.deleteCollectionElement({ 'parent_uid': id, 'uid': oid }, dn=None) else: r = [] elif request.method == 'GET': if oid: r = rdb.getRecord('collection_elements', { 'parent_uid': id, 'uid': oid }, dn=dn) else: r = rdb.getRecord('collection_elements', {'parent_uid': id}, dn=dn) #Find original item and add it to record. for record in r: print('collection element r', record) r_uid = record['uid'] #getRecordTable returns a python dict record['type'] = rdb.getRecordTable(r_uid, dn=dn) #set default field values detail = { 'related': 'not sure', 'link-related': root_url, 'related': 'cousins', 'name': 'what is this?', 'description': 'empty', 'time': 'nowhen' } #Translation for specific types if record['type'] == 'workflow': detail = rdb.getWorkflow({'uid': r_uid}, dn=dn)[0] print('element workflow', detail) detail['related'] = rdb.getWorkflowCompositeID( r_uid, dn=dn).get('alias') links = {} links['link1'] = root_url + '/workflow/' + r_uid links['link2'] = root_url + '/workflow?alias=' + detail[ 'related'] detail['link-related'] = links elif record['type'] == 'dataobject': detail = rdb.getRecord('dataobject', {'uid': r_uid}, dn=dn)[0] detail['related'] = detail.get('uri') detail['link-related'] = root_url + '/dataobject/' + r_uid elif record['type'] == 'dataobject_instance': do_uid = (rdb.getRecord('dataobject_instance', {'uid': record['uid']}, dn=dn)[0]).get('do_uid') detail = rdb.getRecord('dataobject', {'uid': do_uid}, dn=dn)[0] detail['related'] = detail.get('uri') detail['link-related'] = root_url + '/dataobject/' + do_uid elif record['type'] == 'collection': thisdetail = rdb.getRecord('collection', {'uid': r_uid}, dn=dn)[0] detail['related'] = None detail[ 'link-related'] = root_url + '/collection/' + r_uid + '/element' detail['description'] = thisdetail.get('description') detail['name'] = thisdetail.get('name') detail['time'] = thisdetail.get('time') record['name'] = detail['name'] record['description'] = detail['description'] record['time'] = detail['time'] record['related'] = detail['related'] record['link-related'] = detail['link-related'] istatus = 200 # if len(r) == 0: # #istatus = 404 # r=[{'mesg':'No records found', 'number_of_records':0, 'status':404}] return Response(json.dumps(r, cls=MPOSetEncoder), mimetype='application/json', status=istatus)