def install_base_data(): """ Install the application's base data to the database. """ db_connection = get_connection( isolation_level=ISOLATION_LEVEL_READ_COMMITTED ) with db_connection, db_connection.cursor() as cursor: for namespace, predicates in rels.RELATIONS.items(): # Default relationship data. relations_writer.upsert_namespace(namespace, cursor=cursor) namespace_id, = cursor.fetchone() for predicate in predicates: relations_writer.upsert_predicate( {'namespace': namespace_id, 'predicate': predicate}, cursor=cursor ) # Default user data. source_id = source_writer.upsert_source( _config['self']['source'], cursor=cursor ).fetchone()['id'] user_id = source_writer.upsert_user( {'source': source_id, 'name': _config['self']['username']}, cursor=cursor ).fetchone()['id'] # Default namespace data. ns_map = {} for namespace in BASE_NAMESPACES: ns_map[namespace] = object_writer.upsert_namespace( namespace, cursor=cursor ).fetchone()['id'] # Default object data. for obj in BASE_OBJECTS: namespace, pid_id = utils.break_pid(obj) obj_info = object_writer.upsert_object( { 'namespace': ns_map[namespace], 'owner': user_id, 'pid_id': pid_id, }, cursor=cursor ).fetchone() # Add DC DS as Fedora objects have DC and Islandora expects it. foxml.create_default_dc_ds(obj_info['id'], obj, cursor=cursor) db_connection.close() logger.info('Installed base data.')
def object_info_from_raw(pid, cursor=None): """ Get object info from a PID. """ cursor = check_cursor(cursor) namespace, pid_id = utilities.break_pid(pid) cursor.execute( ''' SELECT objects.* FROM objects JOIN pid_namespaces ON objects.namespace = pid_namespaces.id WHERE objects.pid_id = %s AND pid_namespaces.namespace = %s ''', (pid_id, namespace)) return cursor
def delete_datastream_from_raw(pid, dsid, cursor=None): """ Delete a datastream from the repository given a PID and DSID. """ cursor = check_cursor(cursor) namespace, pid_id = utilities.break_pid(pid) cursor.execute( ''' DELETE FROM datastreams USING objects, pid_namespaces WHERE datastreams.object = objects.id AND objects.namespace = pid_namespaces.id AND objects.pid_id = %s AND pid_namespaces.namespace = %s AND datastreams.dsid = %s ''', (pid_id, namespace, dsid)) return cursor
def datastream_from_raw(pid, dsid, cursor=None): """ Query for a datastream record from the repository given a PID and DSID. """ cursor = check_cursor(cursor) namespace, pid_id = utilities.break_pid(pid) cursor.execute( ''' SELECT datastreams.* FROM datastreams JOIN objects ON datastreams.object = objects.id JOIN pid_namespaces ON objects.namespace = pid_namespaces.id WHERE objects.pid_id = %s AND pid_namespaces.namespace = %s AND datastreams.dsid = %s ''', (pid_id, namespace, dsid)) return cursor
def _create_object(self, req, pid): """ Create the new object. """ conn = get_connection(ISOLATION_LEVEL_READ_COMMITTED) with conn, conn.cursor() as cursor: if not pid or pid == 'new': import_pid = None else: import_pid = pid try: # Import FOXML, getting PID. pid = foxml.import_foxml(req.get_param('file').file, req.env['wsgi.identity'].source_id, pid=import_pid, cursor=cursor) except AttributeError: if req.content_length: # Try to import FOXML from request body. pid = foxml.import_foxml( req.stream, req.env['wsgi.identity'].source_id, pid=import_pid, cursor=cursor) else: if not pid or pid == 'new': # Generate PID. raw_namespace = req.get_param( 'namespace', default=_config['default_namespace']) object_writer.get_pid_id(raw_namespace, cursor=cursor) pid_id, namespace = cursor.fetchone() pid = utils.make_pid(raw_namespace, pid_id) else: # Reserve given PID in namespace. raw_namespace, pid_id = utils.break_pid(pid) namespace = cache.repo_object_namespace_id( raw_namespace, cursor=cursor) # Jump up PIDs if needed. object_writer.jump_pids(namespace, pid_id, cursor=cursor) # Figure out the owner's DB ID. owner = self._resolve_owner(req, cursor) # Figure out the log's DB ID. log = resolve_log(req, cursor) try: object_writer.write_object( { 'namespace': namespace, 'state': req.get_param('state', default='A'), 'label': req.get_param('label'), 'log': log, 'pid_id': pid_id, 'owner': owner, }, cursor=cursor) except IntegrityError as e: raise ObjectExistsError(pid) from e foxml.create_default_dc_ds(cursor.fetchone()[0], pid, cursor=cursor) conn.close() return pid
def end(self, tag): """ Internalize data at the end of tags. Raises: ObjectExistsError: The object already exists. """ # Create the object. if tag == '{{{0}}}objectProperties'.format(FOXML_NAMESPACE): object_db_info = {} raw_namespace, object_db_info['pid_id'] = utils.break_pid( self.object_info['PID']) object_db_info['namespace'] = cache.repo_object_namespace_id( raw_namespace, cursor=self.cursor) raw_log = 'Object created through FOXML import.' upsert_log(raw_log, cursor=self.cursor) object_db_info['log'] = self.cursor.fetchone()[0] try: raw_owner = self.object_info['{}{}'.format( relations.FEDORA_MODEL_NAMESPACE, relations.OWNER_PREDICATE)] except KeyError: pass else: upsert_user({ 'name': raw_owner, 'source': self.source }, cursor=self.cursor) object_db_info['owner'] = self.cursor.fetchone()[0] try: object_db_info['created'] = self.object_info['{}{}'.format( relations.FEDORA_MODEL_NAMESPACE, relations.CREATED_DATE_PREDICATE)] except KeyError: pass try: object_db_info['modified'] = self.object_info['{}{}'.format( relations.FEDORA_VIEW_NAMESPACE, relations.LAST_MODIFIED_DATE_PREDICATE)] except KeyError: pass try: object_db_info['state'] = OBJECT_STATE_LABEL_MAP[ self.object_info['{}{}'.format( relations.FEDORA_MODEL_NAMESPACE, relations.STATE_PREDICATE)]] except KeyError: try: object_db_info['state'] = self.object_info['{}{}'.format( relations.FEDORA_MODEL_NAMESPACE, relations.STATE_PREDICATE)] except KeyError: pass object_db_info['label'] = self.object_info['{}{}'.format( relations.FEDORA_MODEL_NAMESPACE, relations.LABEL_PREDICATE)] object_writer.jump_pids(object_db_info['namespace'], object_db_info['pid_id'], cursor=self.cursor) try: object_writer.write_object(object_db_info, cursor=self.cursor) except IntegrityError: raise ObjectExistsError(self.object_info['PID']) self.object_id = self.cursor.fetchone()[0] # Stash content. if (tag == '{{{0}}}xmlContent'.format(FOXML_NAMESPACE) and self.dsid != 'AUDIT'): base_element = self.tree_builder.close() xml_ds = BytesIO(etree.tostring(base_element)) self.ds_info[self.dsid]['versions'][-1]['data'] = xml_ds self.tree_builder = None elif self.tree_builder is not None: self.tree_builder.end(tag) if tag == '{{{0}}}binaryContent'.format(FOXML_NAMESPACE): self.ds_file.seek(0) decoded_file = utils.SpooledTemporaryFile() base64.decode(self.ds_file, decoded_file) self.ds_file.close() self.ds_file = None decoded_file.seek(0) self.ds_info[self.dsid]['versions'][-1]['data'] = decoded_file # Store old and current DSs, passing off RELS/DC. if (tag == '{{{0}}}datastream'.format(FOXML_NAMESPACE) and self.dsid != 'AUDIT'): last_ds = self.ds_info[self.dsid]['versions'].pop() last_ds.update(self.ds_info[self.dsid]) try: last_ds['actually_created'] = ( self.ds_info[self.dsid]['versions'][0]['CREATED']) except IndexError: try: last_ds['actually_created'] = last_ds['CREATED'] except KeyError: last_ds['actually_created'] = None last_ds['CREATED'] = None # Populate relations. if self.dsid == 'DC': internalize_rels_dc(last_ds['data'], self.object_id, purge=False, cursor=self.cursor) self.cursor.fetchall() elif self.dsid == 'RELS-EXT': internalize_rels_ext(last_ds['data'], self.object_id, self.source, purge=False, cursor=self.cursor) self.cursor.fetchall() elif self.dsid == 'RELS-INT': self.rels_int = etree.parse(last_ds['data']) last_ds['data'].seek(0) # Write DS. ds_db_id = self._create_ds(last_ds) # Write old DSs. for ds_version in self.ds_info[self.dsid]['versions']: ds_version.update(self.ds_info[self.dsid]) ds_version['datastream'] = ds_db_id ds_version['actually_created'] = None self._create_ds(ds_version, old=True) # Reset current datastream. self.dsid = None