def get(self): """Get all relations of this record, adding any relations metadata.""" relations = {} for relation_type in current_app.config["PARENT_CHILD_RELATION_TYPES"]: pcr = ParentChildRelation(relation_type) name = relation_type.name # self.record is a child for parent_pid in pcr.parents_of(self.record.pid): child_pid = self.record.pid r = self._build_child(parent_pid, child_pid, name) relations.setdefault(name, []) relations[name].append(r) for relation_type in current_app.config["SIBLINGS_RELATION_TYPES"]: sr = SiblingsRelation(relation_type) name = relation_type.name for related_pid in sr.all(self.record.pid): r = self._build_sibling(related_pid, name) relations.setdefault(name, []) relations[name].append(r) for relation_type in current_app.config["SEQUENCE_RELATION_TYPES"]: sqr = SequenceRelation(relation_type) name = relation_type.name for next_pid in sqr.next_relations(self.record.pid): relations.setdefault("next", []) r = self._build_sequence(next_pid, name) relations["next"].append(r) for previous_pid in sqr.previous_relations(self.record.pid): relations.setdefault("previous", []) r = self._build_sequence(previous_pid, name) relations["previous"].append(r) return relations
def _validate_relation_between_records(self, parent, child, relation_type): """Validate relation between type of records.""" from invenio_app_ils.documents.api import Document from invenio_app_ils.series.api import Series if relation_type.name == "multipart_monograph": pcr = ParentChildRelation(relation_type) relations = pcr.get_relations_by_child(child.pid) if len(relations) > 0: raise RecordRelationsError( "Cannot create a relation `{}` between PID `{}` as parent" " and PID `{}` as child. Record `{}` has already a" " multipart monograph.".format( relation_type.name, parent.pid.pid_value, child.pid.pid_value, child.pid.pid_value, )) # when child is Document, parent is any type of Series is_series_doc = isinstance(child, Document) and isinstance( parent, Series) # when child is Multipart Monograph, parent is only Serials is_serial_mm = (isinstance(child, Series) and isinstance(parent, Series) and child["mode_of_issuance"] == "MULTIPART_MONOGRAPH" and parent["mode_of_issuance"] == "SERIAL") if not (is_series_doc or is_serial_mm): raise RecordRelationsError( "Cannot create a relation `{}` between PID `{}` as parent and " "PID `{}` as child.".format( relation_type.name, parent.pid.pid_value, child.pid.pid_value, )) return True
def add(self, parent, child, relation_type, **kwargs): """Add a new relation between given parent and child records.""" self._validate_relation_type(relation_type) self._validate_relation_between_records( parent=parent, child=child, relation_name=relation_type.name ) pcr = ParentChildRelation(relation_type) pcr.add(parent_pid=parent.pid, child_pid=child.pid) # relation metadata is allowed only for MULTIPART_MONOGRAPH relation_allows_metadata = relation_type in ( MULTIPART_MONOGRAPH_RELATION, SERIAL_RELATION, ) # check for allowed relation metadata (e.g. `volume`) has_allowed_metadata = any( [kwargs.get(metadata) for metadata in self.allowed_metadata] ) if relation_allows_metadata and has_allowed_metadata: # filter and keep only allowed metadata allowed = { k: v for k, v in kwargs.items() if k in self.allowed_metadata } # store relation metadata in the child record RecordRelationsExtraMetadata.add_extra_metadata_to( child, relation_type.name, parent.pid.pid_value, parent.pid.pid_type, **allowed, ) # return the allegedly modified record return child