def create_extended_resource_container(self, extended_resource_type, resource_id, computed_resource_type=None, ext_associations=None, ext_exclude=None): if not self.service_provider or not self.resource_registry: raise Inconsistent("This class is not initialized properly") if extended_resource_type not in getextends(OT.ResourceContainer): raise BadRequest('Requested resource %s is not extended from %s' % ( extended_resource_type, OT.ResourceContainer) ) if computed_resource_type and computed_resource_type not in getextends(OT.ComputedAttributes): raise BadRequest('Requested resource %s is not extended from %s' % ( computed_resource_type, OT.ComputedAttributes) ) resource_object = self.resource_registry.read(resource_id) if not resource_object: raise NotFound("Resource %s does not exist" % resource_id) res_container = IonObject(extended_resource_type) res_container._id = resource_object._id res_container.resource = resource_object self.set_container_field_values(res_container, ext_exclude) self.set_computed_attributes(res_container, computed_resource_type, ext_exclude) self.set_extended_associations(res_container, ext_associations, ext_exclude) res_container.ts_created = get_ion_ts() return res_container
def load_definitions(): """Loads constants for resource, association and life cycle states. Make sure global module variable objects are updated, not replaced, because other modules had already imported them (BAD). """ # Resource Types ot_list = getextends('IonObjectBase') ot_list.append('IonObjectBase') ObjectTypes.clear() ObjectTypes.update(zip(ot_list, ot_list)) # Resource Types rt_list = getextends('Resource') rt_list.append('Resource') ResourceTypes.clear() ResourceTypes.update(zip(rt_list, rt_list)) # Predicate Types pt_list = get_predicate_type_list() PredicateType.clear() PredicateType.update(zip(pt_list, pt_list)) # Compound Associations get_compound_associations_list() # Life cycle states initialize_res_lcsms() LifeCycleStates.clear() allstates = list(CommonResourceLifeCycleSM.BASE_STATES) + CommonResourceLifeCycleSM.STATE_ALIASES.keys() LifeCycleStates.update(zip(allstates, allstates)) # Life cycle events LCE.clear() LCE.update(zip([e.upper() for e in CommonResourceLifeCycleSM.BASE_EVENTS], CommonResourceLifeCycleSM.BASE_EVENTS))
def test_list_resource_types(self): response = self.test_app.get('/ion-service/list_resource_types') self.check_response_headers(response) self.assertIn(GATEWAY_RESPONSE, response.json['data']) expected_type_list = getextends('Resource') self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list)) result_set = set(response.json['data'][GATEWAY_RESPONSE]) expected_type_set = set(expected_type_list) intersect_result = expected_type_set.intersection(result_set) self.assertEqual(len(intersect_result), len(expected_type_list)) response = self.test_app.get('/ion-service/list_resource_types?type=InformationResource') self.check_response_headers(response) self.assertIn(GATEWAY_RESPONSE, response.json['data']) expected_type_list = getextends('InformationResource') self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list)) result_set = set(response.json['data'][GATEWAY_RESPONSE]) expected_type_set = set(expected_type_list) intersect_result = expected_type_set.intersection(result_set) self.assertEqual(len(intersect_result), len(expected_type_list)) response = self.test_app.get('/ion-service/list_resource_types?type=TaskableResource') self.check_response_headers(response) self.assertIn(GATEWAY_RESPONSE, response.json['data']) expected_type_list = getextends('TaskableResource') self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list)) result_set = set(response.json['data'][GATEWAY_RESPONSE]) expected_type_set = set(expected_type_list) intersect_result = expected_type_set.intersection(result_set) self.assertEqual(len(intersect_result), len(expected_type_list)) response = self.test_app.get('/ion-service/list_resource_types?type=MyFakeResource') self.check_response_headers(response) self.assertIn(GATEWAY_ERROR, response.json['data']) self.assertIn('KeyError', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION]) self.assertIn('MyFakeResource', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE]) self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])
def create_extended_resource_container(self, extended_resource_type, resource_id, computed_resource_type=None, ext_associations=None, ext_exclude=None): overall_start_time = time.time() if not isinstance(resource_id, types.StringType): raise Inconsistent("The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if extended_resource_type not in getextends(OT.ResourceContainer): raise BadRequest('The requested resource %s is not extended from %s' % (extended_resource_type, OT.ResourceContainer)) if computed_resource_type and computed_resource_type not in getextends(OT.ComputedAttributes): raise BadRequest('The requested resource %s is not extended from %s' % (computed_resource_type, OT.ComputedAttributes)) resource_object = self._rr.read(resource_id) if not resource_object: raise NotFound("The Resource %s does not exist" % resource_id) res_container = IonObject(extended_resource_type) # @TODO - replace with object level decorators and raise exceptions if not hasattr(res_container, 'origin_resource_type'): log.error('The requested resource %s does not contain a properly set origin_resource_type field.' , extended_resource_type) #raise Inconsistent('The requested resource %s does not contain a properly set origin_resource_type field.' % extended_resource_type) if hasattr(res_container, 'origin_resource_type') and res_container.origin_resource_type != resource_object.type_\ and not issubtype(resource_object.type_, res_container.origin_resource_type): log.error('The origin_resource_type of the requested resource %s(%s) does not match the type of the specified resource id(%s).' % ( extended_resource_type, res_container.origin_resource_type, resource_object.type_)) #raise Inconsistent('The origin_resource_type of the requested resource %s(%s) does not match the type of the specified resource id(%s).' % (extended_resource_type, res_container.origin_resource_type, resource_object.type_)) res_container._id = resource_object._id res_container.resource = resource_object self.set_container_lcstate_info(res_container) self.set_container_field_values(res_container, ext_exclude) self.set_computed_attributes(res_container, computed_resource_type, ext_exclude) self.set_extended_associations(res_container, ext_associations, ext_exclude) res_container.ts_created = get_ion_ts() overall_stop_time = time.time() log.debug("Time to process extended resource container %s %f secs", extended_resource_type, overall_stop_time - overall_start_time ) return res_container
def create_prepare_resource_support(self, resource_id="", prepare_resource_type=None, origin_resource_type=None): if not isinstance(resource_id, types.StringType): raise Inconsistent("The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if prepare_resource_type is not None and prepare_resource_type not in getextends(OT.ResourcePrepareSupport): raise BadRequest('The requested resource %s is not extended from %s' % (prepare_resource_type, OT.ResourcePrepareSupport)) resource_data = IonObject(prepare_resource_type) # Check to make sure the extended resource decorator raise OriginResourceType matches the type of the resource type origin_resource_decorator = resource_data.get_class_decorator_value('OriginResourceType') if origin_resource_decorator is None and origin_resource_type is None: raise NotFound('OriginResourceType decorator not found in object specification %s', prepare_resource_type) origin_resource_type = origin_resource_type if origin_resource_type is not None else origin_resource_decorator if origin_resource_type is None: raise NotFound('OriginResourceType decorator not found in object specification %s', prepare_resource_type) resource_object = None if resource_id: resource_object = self._rr.read(resource_id) if origin_resource_type != resource_object.type_ and not issubtype(resource_object.type_, origin_resource_type): raise Inconsistent('The OriginResourceType decorator of the requested resource %s(%s) does not match the type of the specified resource id(%s).' % ( prepare_resource_type, origin_resource_type, resource_object.type_)) resource_data._id = resource_object._id else: resource_object = IonObject(origin_resource_type) resource_data.resource = resource_object resource_data.resource_schema = get_object_schema(origin_resource_type) for field in resource_data._schema: deco_value = resource_data.get_decorator_value(field, 'AssociatedResources') assoc_dict = {} if deco_value is not None: if deco_value.find(',') == -1: associated_resources = [deco_value] else: associated_resources = deco_value.split(',') for res in associated_resources: assoc = self.get_associated_resource_info(origin_resource_type, resource_id, res) assoc_dict[assoc.key] = assoc setattr(resource_data, field, assoc_dict) continue return resource_data
def load_definitions(): """Loads constants for resource, association and life cycle states. Make sure global module variable objects are updated, not replaced, because other modules had already imported them (BAD). """ # Resource Types ot_list = getextends("IonObjectBase") ot_list.append("IonObjectBase") ObjectTypes.clear() ObjectTypes.update(zip(ot_list, ot_list)) ObjectTypes.lock() # Resource Types rt_list = getextends("Resource") rt_list.append("Resource") ResourceTypes.clear() ResourceTypes.update(zip(rt_list, rt_list)) ResourceTypes.lock() # Predicate Types pt_list = get_predicate_type_list() PredicateType.clear() PredicateType.update(zip(pt_list, pt_list)) PredicateType.lock() # Compound Associations get_compound_associations_list() # Lifecycle, availability states and transition events initialize_res_lcsms() lcstates, avstates, fsmevents = get_all_lcsm_names() LifeCycleStates.clear() LifeCycleStates.update(zip(lcstates, lcstates)) LifeCycleStates.lock() AvailabilityStates.clear() AvailabilityStates.update(zip(avstates, avstates)) AvailabilityStates.lock() LCE.clear() LCE.update(zip([e.upper() for e in fsmevents], fsmevents)) LCE.lock()
def list_resource_types(): try: #Validate requesting user and expiry and add governance headers ion_actor_id, expiry = get_governance_info_from_request() ion_actor_id, expiry = validate_request(ion_actor_id, expiry) #Look to see if a specific resource type has been specified - if not default to all if request.args.has_key('type'): resultSet = set(getextends(request.args['type'])) if getextends(request.args['type']) is not None else set() else: type_list = getextends('Resource') resultSet = set(type_list) ret_list = [] for res in sorted(resultSet): ret_list.append(res) return gateway_json_response(ret_list) except Exception, e: return build_error_response(e)
def list_resource_types(): try: #Look to see if a specific resource type has been specified - if not default to all if request.args.has_key('type'): resultSet = set(getextends(request.args['type'])) if getextends(request.args['type']) is not None else set() else: type_list = getextends('Resource') resultSet = set(type_list) ret_list = [] for res in sorted(resultSet): ret_list.append(res) return json_response({ GATEWAY_RESPONSE :ret_list } ) except Exception, e: return build_error_response(e)
def process_list_resource_types(): try: type_list = set(getextends("Resource")) fragments = [build_standard_menu(), "<h1>List of Resource Types</h1>", "<p>"] for restype in sorted(type_list): fragments.append("<a href='/list/%s'>%s</a>, " % (restype, restype)) fragments.append("</p>") content = "\n".join(fragments) return build_page(content) except Exception, e: return build_error_page(traceback.format_exc())
def build_res_extends(restype): fragments = [ "<p><i>Extends:</i> ", ] extendslist = [parent.__name__ for parent in _get_object_class(restype).__mro__ if parent.__name__ not in ['IonObjectBase','object']] for extend in extendslist: if extend != restype: fragments.append(build_link(extend, "/list/%s" % extend)) fragments.append(", ") fragments.append("<br><i>Extended by:</i> ") for extends in sorted(getextends(restype)): if extends != restype: fragments.append(build_link(extends, "/list/%s" % extends)) fragments.append(", ") fragments.append("</p>") return "".join(fragments)
def load_definitions(): """Loads constants for resource, association and life cycle states. Make sure global module variable objects are updated, not replaced, because other modules had already imported them (BAD). """ # Resource Types rt_list = getextends('Resource') rt_list.append('Resource') ResourceTypes.clear() ResourceTypes.update(zip(rt_list, rt_list)) # Association Types at_list = get_predicate_type_list() PredicateType.clear() PredicateType.update(zip(at_list, at_list)) # Life cycle states initialize_res_lcsms() LifeCycleStates.clear() allstates = list(ResourceLifeCycleSM.BASE_STATES) + ResourceLifeCycleSM.STATE_ALIASES.keys() LifeCycleStates.update(zip(allstates, allstates)) LCE.clear() LCE.update(zip(ResourceLifeCycleSM.BASE_EVENTS, ResourceLifeCycleSM.BASE_EVENTS))
def create_association_mult(self, assoc_list=None): """ Create multiple associations between two IonObjects with a given predicate. @param assoc_list A list of 3-tuples of (subject, predicate, object). Subject/object can be str or object """ if not assoc_list: return [] lookup_rid = set() for s, p, o in assoc_list: if type(s) is str: lookup_rid.add(s) if type(o) is str: lookup_rid.add(o) lookup_rid = list(lookup_rid) lookup_obj = self.read_mult(lookup_rid) if lookup_rid else [] res_by_id = dict(zip(lookup_rid, lookup_obj)) create_ts = get_ion_ts() new_assoc_list = [] for s, p, o in assoc_list: new_s = s new_o = o if type(s) is str: new_s = res_by_id[s] if not new_s: raise NotFound("Subject %s not found" % s) else: if "_id" not in s: raise BadRequest("Subject id not available") if type(o) is str: new_o = res_by_id[o] if not new_o: raise NotFound("Object %s not found" % o) else: if "_id" not in object: raise BadRequest("Object id not available") # Check that subject and object type are permitted by association definition if p not in Predicates: raise BadRequest("Predicate unknown %s" % p) pt = Predicates.get(p) if not new_s.type_ in pt['domain']: found_st = False for domt in pt['domain']: if new_s.type_ in getextends(domt): found_st = True break if not found_st: raise BadRequest("Illegal subject type %s for predicate %s" % (new_s.type_, p)) if not new_o.type_ in pt['range']: found_ot = False for rant in pt['range']: if new_o.type_ in getextends(rant): found_ot = True break if not found_ot: raise BadRequest("Illegal object type %s for predicate %s" % (new_o.type_, p)) # Skip duplicate check assoc = IonObject("Association", s=new_s._id, st=new_s.type_, p=p, o=new_o._id, ot=new_o.type_, ts=create_ts) new_assoc_list.append(assoc) new_assoc_ids = [create_unique_association_id() for i in xrange(len(new_assoc_list))] return self.rr_store.create_mult(new_assoc_list, new_assoc_ids)
def create_association(self, subject=None, predicate=None, object=None, assoc_type=None): """ Create an association between two IonObjects with a given predicate @param assoc_type DEPRECATED """ if not (subject and predicate and object): raise BadRequest("Association must have all elements set") if type(subject) is str: subject_id = subject subject = self.read(subject_id) subject_type = subject.type_ else: if "_id" not in subject: raise BadRequest("Subject id not available") subject_id = subject._id subject_type = subject.type_ if type(object) is str: object_id = object object = self.read(object_id) object_type = object.type_ else: if "_id" not in object: raise BadRequest("Object id not available") object_id = object._id object_type = object.type_ # Check that subject and object type are permitted by association definition try: pt = Predicates.get(predicate) except AttributeError: raise BadRequest("Predicate unknown %s" % predicate) if not subject_type in pt['domain']: found_st = False for domt in pt['domain']: if subject_type in getextends(domt): found_st = True break if not found_st: raise BadRequest("Illegal subject type %s for predicate %s" % (subject_type, predicate)) if not object_type in pt['range']: found_ot = False for rant in pt['range']: if object_type in getextends(rant): found_ot = True break if not found_ot: raise BadRequest("Illegal object type %s for predicate %s" % (object_type, predicate)) # Finally, ensure this isn't a duplicate assoc_list = self.find_associations(subject_id, predicate, object_id, id_only=False) if len(assoc_list) != 0: assoc = assoc_list[0] #print "**** Found associations:" #import pprint #pprint.pprint(assoc_list) raise BadRequest("Association between %s and %s with predicate %s already exists" % (subject_id, object_id, predicate)) assoc = IonObject("Association", s=subject_id, st=subject_type, p=predicate, o=object_id, ot=object_type, ts=get_ion_ts()) return self.rr_store.create(assoc, create_unique_association_id())
def is_predicate_association_extension(self, predicate, predicate_type, res): for predt in predicate[predicate_type]: if res in getextends(predt): return True return False
def create_prepare_resource_support(self, resource_id="", prepare_resource_type=None, origin_resource_type=None): if not isinstance(resource_id, types.StringType): raise Inconsistent( "The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if prepare_resource_type is not None and prepare_resource_type not in getextends( OT.ResourcePrepareSupport): raise BadRequest( 'The requested resource %s is not extended from %s' % (prepare_resource_type, OT.ResourcePrepareSupport)) resource_data = IonObject(prepare_resource_type) # Check to make sure the extended resource decorator raise OriginResourceType matches the type of the resource type origin_resource_decorator = resource_data.get_class_decorator_value( 'OriginResourceType') if origin_resource_decorator is None and origin_resource_type is None: raise NotFound( 'OriginResourceType decorator not found in object specification %s', prepare_resource_type) origin_resource_type = origin_resource_type if origin_resource_type is not None else origin_resource_decorator if origin_resource_type is None: raise NotFound( 'OriginResourceType decorator not found in object specification %s', prepare_resource_type) resource_object = None if resource_id: resource_object = self._rr.read(resource_id) if origin_resource_type != resource_object.type_ and not issubtype( resource_object.type_, origin_resource_type): raise Inconsistent( 'The OriginResourceType decorator of the requested resource %s(%s) does not match the type of the specified resource id(%s).' % (prepare_resource_type, origin_resource_type, resource_object.type_)) resource_data._id = resource_object._id else: resource_object = IonObject(origin_resource_type) resource_data.resource = resource_object resource_data.resource_schema = get_object_schema(origin_resource_type) for field in resource_data._schema: deco_value = resource_data.get_decorator_value( field, 'AssociatedResources') assoc_dict = {} if deco_value is not None: if deco_value.find(',') == -1: associated_resources = [deco_value] else: associated_resources = deco_value.split(',') for res in associated_resources: assoc = self.get_associated_resource_info( origin_resource_type, resource_id, res) assoc_dict[assoc.key] = assoc setattr(resource_data, field, assoc_dict) continue return resource_data
def create_extended_resource_container(self, extended_resource_type, resource_id, computed_resource_type=None, ext_associations=None, ext_exclude=None, **kwargs): """ Returns an extended resource container for a given resource_id. """ overall_start_time = time.time() self.ctx = None # Clear the context in case this instance gets reused if not isinstance(resource_id, types.StringType): raise Inconsistent( "The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if extended_resource_type not in getextends(OT.ResourceContainer): raise BadRequest( 'The requested resource %s is not extended from %s' % (extended_resource_type, OT.ResourceContainer)) if computed_resource_type and computed_resource_type not in getextends( OT.BaseComputedAttributes): raise BadRequest( 'The requested resource %s is not extended from %s' % (computed_resource_type, OT.BaseComputedAttributes)) resource_object = self._rr.read(resource_id) if not resource_object: raise NotFound("The Resource %s does not exist" % resource_id) res_container = IonObject(extended_resource_type) # Check to make sure the extended resource decorator raise OriginResourceType matches the type of the resource type originResourceType = res_container.get_class_decorator_value( 'OriginResourceType') if originResourceType is None: log.error( 'The requested extended resource %s does not contain an OriginResourceType decorator.', extended_resource_type) elif originResourceType != resource_object.type_ and not issubtype( resource_object.type_, originResourceType): raise Inconsistent( 'The OriginResourceType decorator of the requested resource %s(%s) does not match the type of the specified resource id(%s).' % (extended_resource_type, originResourceType, resource_object.type_)) res_container._id = resource_object._id res_container.resource = resource_object # Initialize context object field and load resource associations self._prepare_context(resource_object._id) # Fill lcstate related resource container fields self.set_container_lcstate_info(res_container) # Fill resource container fields self.set_container_field_values(res_container, ext_exclude, **kwargs) # Fill computed attributes self.set_computed_attributes(res_container, computed_resource_type, ext_exclude, **kwargs) # Fill additional associations self.set_extended_associations(res_container, ext_associations, ext_exclude) res_container.ts_created = get_ion_ts() overall_stop_time = time.time() log.debug("Time to process extended resource container %s %f secs", extended_resource_type, overall_stop_time - overall_start_time) #log.info("ResourceContainer: %s" % res_container) return res_container
def get_associated_resource_info(self, origin_resource_type="", resource_id="", assoc_resource_type=None): if not origin_resource_type: raise Inconsistent("The parameter origin_resource_type is not set") if not isinstance(resource_id, types.StringType): raise Inconsistent("The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if assoc_resource_type is not None and assoc_resource_type not in getextends(OT.AssociatedResources): raise BadRequest('The requested resource %s is not extended from %s' % (assoc_resource_type, OT.AssociatedResources)) resource_data = IonObject(assoc_resource_type) for field in resource_data._schema: deco_value = resource_data.get_decorator_value(field, 'ResourceType') if deco_value is not None: #Set the type of the associated resource to be used as the key in dict of associations setattr(resource_data, 'resource_type', deco_value) res_list,_ = self._rr.find_resources(restype=deco_value, id_only=False) exclude_lcs_filter_value = resource_data.get_decorator_value(field, 'ExcludeLifecycleStates') if exclude_lcs_filter_value is not None and exclude_lcs_filter_value.find(',') > -1: exclude_filter = exclude_lcs_filter_value.split(',') res_list = [res for res in res_list if res.lcstate not in exclude_filter ] #Look for ResourceSPOFilter filter and filter above results to exclude other resources already assigned #This filter MUST be a comma separated value of Subject, Predicate, Object res_filter_value = resource_data.get_decorator_value(field, 'ResourceSPOFilter') if res_filter_value is not None and res_filter_value.find(',') > -1: assoc_filter = res_filter_value.split(',') res_associations = self._rr.find_associations(predicate=assoc_filter[1], id_only=False) assoc_list = [a for a in res_associations if a.st==assoc_filter[0] and a.ot==assoc_filter[2]] def resource_available(res): for assoc in assoc_list: if assoc.st == origin_resource_type: if assoc.o == res._id: if not resource_id: return False if assoc.s == resource_id: return True else: return False else: if assoc.s == res._id: if not resource_id: return False if assoc.o == resource_id: return True else: return False return True #Iterate over the list and remove any object which are assigned to other resources and not the target resource final_list = [] final_list.extend( [res for res in res_list if resource_available(res)]) setattr(resource_data, field, final_list) else: setattr(resource_data, field, res_list) continue deco_value = resource_data.get_decorator_value(field, 'Association') if deco_value is not None: #If the association is related to an existing resource and this is a create then skip if not resource_id and ( resource_data.is_decorator(field, 'ResourceSubject') or resource_data.is_decorator(field, 'ResourceObject')): continue resource_sub = resource_id if resource_data.is_decorator(field, 'ResourceSubject') else None resource_obj = resource_id if resource_data.is_decorator(field, 'ResourceObject') else None assoc_list = self._rr.find_associations(subject=resource_sub, predicate=deco_value, object=resource_obj, id_only=False) subject_type = resource_data.get_decorator_value(field, 'SubjectType') if subject_type is not None: assoc_list = [assoc for assoc in assoc_list if ( assoc.st == subject_type )] object_type = resource_data.get_decorator_value(field, 'ObjectType') if object_type is not None: assoc_list = [assoc for assoc in assoc_list if ( assoc.ot == object_type )] setattr(resource_data, field, assoc_list) continue return resource_data
def my_getextends(iontype): try: return getextends(iontype) except KeyError: return [iontype]
def create_association(self, subject=None, predicate=None, obj=None, assoc_type="H2H"): """ Create an association between two IonObjects with a given predicate """ if not subject or not predicate or not obj: raise BadRequest("Association must have all elements set") if type(subject) is str: subject_id = subject subject = self.read(subject_id) else: if "_id" not in subject or "_rev" not in subject: raise BadRequest("Subject id or rev not available") subject_id = subject._id st = type(subject).__name__ if type(obj) is str: object_id = obj obj = self.read(object_id) else: if "_id" not in obj or "_rev" not in obj: raise BadRequest("Object id or rev not available") object_id = obj._id ot = type(obj).__name__ assoc_type = assoc_type or "H2H" if not assoc_type in ("H2H", "R2R", "H2R", "R2H", "R2R"): raise BadRequest("Unsupported assoc_type: %s" % assoc_type) # Check that subject and object type are permitted by association definition # Note: Need import here, so that import orders are not screwed up from pyon.core.registry import getextends from pyon.ion.resource import Predicates from pyon.core.bootstrap import IonObject try: at = Predicates.get(predicate) except AttributeError: raise BadRequest("Predicate unknown %s" % predicate) if not st in at["domain"]: found_st = False for domt in at["domain"]: if st in getextends(domt): found_st = True break if not found_st: raise BadRequest("Illegal subject type %s for predicate %s" % (st, predicate)) if not ot in at["range"]: found_ot = False for rant in at["range"]: if ot in getextends(rant): found_ot = True break if not found_ot: raise BadRequest("Illegal object type %s for predicate %s" % (ot, predicate)) assoc = IonObject( "Association", at=assoc_type, s=subject_id, st=st, srv=subject._rev, p=predicate, o=object_id, ot=ot, orv=obj._rev, ts=get_ion_ts(), ) return self.create(assoc)
def create_association(self, subject=None, predicate=None, obj=None, assoc_type=AT.H2H): """ Create an association between two IonObjects with a given predicate """ if not subject or not predicate or not obj: raise BadRequest("Association must have all elements set") if type(subject) is str: subject_id = subject subject = self.read(subject_id) else: if "_id" not in subject or "_rev" not in subject: raise BadRequest("Subject id or rev not available") subject_id = subject._id st = type(subject).__name__ if type(obj) is str: object_id = obj obj = self.read(object_id) else: if "_id" not in obj or "_rev" not in obj: raise BadRequest("Object id or rev not available") object_id = obj._id ot = type(obj).__name__ assoc_type = assoc_type or AT.H2H if not assoc_type in AT: raise BadRequest("Unsupported assoc_type: %s" % assoc_type) # Check that subject and object type are permitted by association definition # Note: Need import here, so that import orders are not screwed up from pyon.core.registry import getextends from pyon.ion.resource import Predicates from pyon.core.bootstrap import IonObject try: pt = Predicates.get(predicate) except AttributeError: raise BadRequest("Predicate unknown %s" % predicate) if not st in pt['domain']: found_st = False for domt in pt['domain']: if st in getextends(domt): found_st = True break if not found_st: raise BadRequest("Illegal subject type %s for predicate %s" % (st, predicate)) if not ot in pt['range']: found_ot = False for rant in pt['range']: if ot in getextends(rant): found_ot = True break if not found_ot: raise BadRequest("Illegal object type %s for predicate %s" % (ot, predicate)) # Finally, ensure this isn't a duplicate assoc_list = self.find_associations(subject, predicate, obj, assoc_type, False) if len(assoc_list) != 0: assoc = assoc_list[0] if assoc_type == AT.H2H: raise BadRequest("Association between %s and %s with predicate %s and type %s already exists" % (subject, obj, predicate, assoc_type)) else: if subject._rev == assoc.srv and object._rev == assoc.orv: raise BadRequest("Association between %s and %s with predicate %s and type %s already exists" % (subject, obj, predicate, assoc_type)) assoc = IonObject("Association", at=assoc_type, s=subject_id, st=st, srv=subject._rev, p=predicate, o=object_id, ot=ot, orv=obj._rev, ts=get_ion_ts()) return self.create(assoc)
def create_extended_resource_container( self, extended_resource_type, resource_id, computed_resource_type=None, ext_associations=None, ext_exclude=None, **kwargs ): """ Returns an extended resource container for a given resource_id. """ overall_start_time = time.time() self.ctx = None # Clear the context in case this instance gets reused if not isinstance(resource_id, types.StringType): raise Inconsistent("The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if extended_resource_type not in getextends(OT.ResourceContainer): raise BadRequest( "The requested resource %s is not extended from %s" % (extended_resource_type, OT.ResourceContainer) ) if computed_resource_type and computed_resource_type not in getextends(OT.BaseComputedAttributes): raise BadRequest( "The requested resource %s is not extended from %s" % (computed_resource_type, OT.BaseComputedAttributes) ) resource_object = self._rr.read(resource_id) if not resource_object: raise NotFound("The Resource %s does not exist" % resource_id) res_container = IonObject(extended_resource_type) # Check to make sure the extended resource decorator raise OriginResourceType matches the type of the resource type originResourceType = res_container.get_class_decorator_value("OriginResourceType") if originResourceType is None: log.error( "The requested extended resource %s does not contain an OriginResourceType decorator.", extended_resource_type, ) elif originResourceType != resource_object.type_ and not issubtype(resource_object.type_, originResourceType): raise Inconsistent( "The OriginResourceType decorator of the requested resource %s(%s) does not match the type of the specified resource id(%s)." % (extended_resource_type, originResourceType, resource_object.type_) ) res_container._id = resource_object._id res_container.resource = resource_object # Initialize context object field and load resource associations self._prepare_context(resource_object._id) # Fill lcstate related resource container fields self.set_container_lcstate_info(res_container) # Fill resource container info; currently only type_version self.set_res_container_info(res_container) # Fill resource container fields self.set_container_field_values(res_container, ext_exclude, **kwargs) # Fill computed attributes self.set_computed_attributes(res_container, computed_resource_type, ext_exclude, **kwargs) # Fill additional associations self.set_extended_associations(res_container, ext_associations, ext_exclude) res_container.ts_created = get_ion_ts() overall_stop_time = time.time() log.debug( "Time to process extended resource container %s %f secs", extended_resource_type, overall_stop_time - overall_start_time, ) # log.info("ResourceContainer: %s" % res_container) return res_container
def get_associated_resource_info(self, origin_resource_type="", resource_id="", assoc_resource_type=None): if not origin_resource_type: raise Inconsistent("The parameter origin_resource_type is not set") if not isinstance(resource_id, types.StringType): raise Inconsistent("The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if assoc_resource_type is not None and assoc_resource_type not in getextends(OT.AssociatedResources): raise BadRequest( "The requested resource %s is not extended from %s" % (assoc_resource_type, OT.AssociatedResources) ) resource_data = IonObject(assoc_resource_type) log.debug("get_associated_resource_info: %s", assoc_resource_type) for field in resource_data._schema: deco_value = resource_data.get_decorator_value(field, "ResourceType") if deco_value is not None: # Set the type of the associated resource to be used as the key in dict of associations setattr(resource_data, "resource_type", deco_value) res_list, _ = self._rr.find_resources(restype=deco_value, id_only=False) exclude_lcs_filter_value = resource_data.get_decorator_value(field, "ExcludeLifecycleStates") if exclude_lcs_filter_value is not None and exclude_lcs_filter_value.find(",") > -1: exclude_filter = exclude_lcs_filter_value.split(",") res_list = [res for res in res_list if res.lcstate not in exclude_filter] # Look for ResourceSPOFilter filter and filter above results to exclude other resources already assigned # This filter MUST be a comma separated value of Subject, Predicate, Object res_filter_value = resource_data.get_decorator_value(field, "ResourceSPOFilter") if res_filter_value is not None and res_filter_value.find(",") > -1: assoc_filter = res_filter_value.split(",") res_associations = self._rr.find_associations(predicate=assoc_filter[1], id_only=False) assoc_list = [a for a in res_associations if a.st == assoc_filter[0] and a.ot == assoc_filter[2]] def resource_available(res): # give me a list of associations relevent to the passed in resource rel_assocs = [ a for a in assoc_list if res._id == (a.o if a.st == origin_resource_type else a.s) ] # of those resources, give me the ids of resources whos types match what i am currently building for assocs = [(a.s if a.st == origin_resource_type else a.o) for a in rel_assocs] # return true if there are no associations for the resource in question, or it has an association to # the current resource we are building for return len(assocs) == 0 or resource_id in assocs # Iterate over the list and remove any object which are assigned to other resources and not the target resource final_list = [] final_list.extend([res for res in res_list if resource_available(res)]) setattr(resource_data, field, final_list) else: setattr(resource_data, field, res_list) continue deco_value = resource_data.get_decorator_value(field, "Association") if deco_value is not None: # If the association is related to an existing resource and this is a create then skip if not resource_id and ( resource_data.is_decorator(field, "ResourceSubject") or resource_data.is_decorator(field, "ResourceObject") ): continue resource_sub = resource_id if resource_data.is_decorator(field, "ResourceSubject") else None resource_obj = resource_id if resource_data.is_decorator(field, "ResourceObject") else None assoc_list = self._rr.find_associations( subject=resource_sub, predicate=deco_value, object=resource_obj, id_only=False ) subject_type = resource_data.get_decorator_value(field, "SubjectType") if subject_type is not None: assoc_list = [assoc for assoc in assoc_list if (assoc.st == subject_type)] object_type = resource_data.get_decorator_value(field, "ObjectType") if object_type is not None: assoc_list = [assoc for assoc in assoc_list if (assoc.ot == object_type)] setattr(resource_data, field, assoc_list) continue # set key if we have one key = resource_data.get_class_decorator_value("Key") if key is None: resource_data.key = resource_data.resource_type else: resource_data.key = key return resource_data
def get_associated_resource_info(self, origin_resource_type="", resource_id="", assoc_resource_type=None): if not origin_resource_type: raise Inconsistent("The parameter origin_resource_type is not set") if not isinstance(resource_id, types.StringType): raise Inconsistent( "The parameter resource_id is not a single resource id string") if not self.service_provider or not self._rr: raise Inconsistent("This class is not initialized properly") if assoc_resource_type is not None and assoc_resource_type not in getextends( OT.AssociatedResources): raise BadRequest( 'The requested resource %s is not extended from %s' % (assoc_resource_type, OT.AssociatedResources)) resource_data = IonObject(assoc_resource_type) log.debug("get_associated_resource_info: %s", assoc_resource_type) for field in resource_data._schema: deco_value = resource_data.get_decorator_value( field, 'ResourceType') if deco_value is not None: #Set the type of the associated resource to be used as the key in dict of associations setattr(resource_data, 'resource_type', deco_value) res_list, _ = self._rr.find_resources(restype=deco_value, id_only=False) exclude_lcs_filter_value = resource_data.get_decorator_value( field, 'ExcludeLifecycleStates') if exclude_lcs_filter_value is not None and exclude_lcs_filter_value.find( ',') > -1: exclude_filter = exclude_lcs_filter_value.split(',') res_list = [ res for res in res_list if res.lcstate not in exclude_filter ] #Look for ResourceSPOFilter filter and filter above results to exclude other resources already assigned #This filter MUST be a comma separated value of Subject, Predicate, Object res_filter_value = resource_data.get_decorator_value( field, 'ResourceSPOFilter') if res_filter_value is not None and res_filter_value.find( ',') > -1: assoc_filter = res_filter_value.split(',') res_associations = self._rr.find_associations( predicate=assoc_filter[1], id_only=False) assoc_list = [ a for a in res_associations if a.st == assoc_filter[0] and a.ot == assoc_filter[2] ] def resource_available(res): # give me a list of associations relevent to the passed in resource rel_assocs = [ a for a in assoc_list if res._id == ( a.o if a.st == origin_resource_type else a.s) ] # of those resources, give me the ids of resources whos types match what i am currently building for assocs = [ (a.s if a.st == origin_resource_type else a.o) for a in rel_assocs ] # return true if there are no associations for the resource in question, or it has an association to # the current resource we are building for return len(assocs) == 0 or resource_id in assocs #Iterate over the list and remove any object which are assigned to other resources and not the target resource final_list = [] final_list.extend( [res for res in res_list if resource_available(res)]) setattr(resource_data, field, final_list) else: setattr(resource_data, field, res_list) continue deco_value = resource_data.get_decorator_value( field, 'Association') if deco_value is not None: #If the association is related to an existing resource and this is a create then skip if not resource_id and ( resource_data.is_decorator(field, 'ResourceSubject') or resource_data.is_decorator(field, 'ResourceObject')): continue resource_sub = resource_id if resource_data.is_decorator( field, 'ResourceSubject') else None resource_obj = resource_id if resource_data.is_decorator( field, 'ResourceObject') else None assoc_list = self._rr.find_associations(subject=resource_sub, predicate=deco_value, object=resource_obj, id_only=False) subject_type = resource_data.get_decorator_value( field, 'SubjectType') if subject_type is not None: assoc_list = [ assoc for assoc in assoc_list if (assoc.st == subject_type) ] object_type = resource_data.get_decorator_value( field, 'ObjectType') if object_type is not None: assoc_list = [ assoc for assoc in assoc_list if (assoc.ot == object_type) ] setattr(resource_data, field, assoc_list) continue # set key if we have one key = resource_data.get_class_decorator_value('Key') if key is None: resource_data.key = resource_data.resource_type else: resource_data.key = key return resource_data