Exemple #1
0
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.')
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
    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
Exemple #6
0
    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