Package org.dspace.rdf

Source Code of org.dspace.rdf.RDFConsumer$DSOIdentifier

/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/

package org.dspace.rdf;

import com.hp.hpl.jena.rdf.model.Model;
import java.sql.SQLException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.Site;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.event.Consumer;
import org.dspace.event.Event;

/**
*
* @author Pascal-Nicolas Becker (dspace -at- pascal -hyphen- becker -dot- de)
*/
public class RDFConsumer implements Consumer
{
    private static final Logger log = Logger.getLogger(RDFConsumer.class);
   
    protected Deque<DSOIdentifier> toConvert;
    protected Deque<DSOIdentifier> toDelete;

    @Override
    public void consume(Context ctx, Event event)
            throws SQLException
    {
        if (this.toConvert == null)
        {
            log.debug("Initalized first queue.");
            this.toConvert = new LinkedList<>();
        }
        if (this.toDelete == null)
        {
            log.debug("Initalized second queue.");
            this.toDelete = new LinkedList<>();
        }
       
        int sType = event.getSubjectType();
        switch (sType)
        {
            case (Constants.BITSTREAM) :
            {
                this.consumeBitstream(ctx, event);
            }
            case (Constants.BUNDLE) :
            {
                this.consumeBundles(ctx, event);
                return;
            }
            case (Constants.ITEM) :
            {
                this.consumeCommunityCollectionItem(ctx, event);
                return;
            }
            case (Constants.COLLECTION) :
            {
                this.consumeCommunityCollectionItem(ctx, event);
                return;
            }
            case (Constants.COMMUNITY) :
            {
                this.consumeCommunityCollectionItem(ctx, event);
                return;
            }
            case (Constants.SITE) :
            {
                this.consumeSite(ctx,event);
                return;
            }
            default:
            {
                log.warn("RDFConsumer should not have been given this kind of "
                        + "subject in an event, skipping: " + event.toString());
            }
        }
       
    }
   
    public void consumeBitstream(Context ctx, Event event) throws SQLException
    {
        if (event.getEventType() == Event.MODIFY
                || event.getEventType() == Event.MODIFY_METADATA)
        {
            Bitstream bitstream = Bitstream.find(ctx, event.getSubjectID());
            if (bitstream == null)
            {
                log.warn("Cannot find bitstream " + event.getSubjectID() + "! "
                        + "Ignoring, as it is likely it was deleted "
                        + "and we'll cover it by a REMOVE event on its bundle.");
                return;
            }
            Bundle[] bundles = bitstream.getBundles();
            for (Bundle b : bundles)
            {
                Item[] items = b.getItems();
                for (Item i : items)
                {
                    DSOIdentifier id = new DSOIdentifier(i, ctx);
                    if (!this.toDelete.contains(id) && !this.toConvert.contains(id))
                    {
                        this.toConvert.addLast(id);
                    }
                }
               
            }
            return;
        }

        // ignore create and delete event on Bitstreams, as they should be
        // reported as ADD and REMOVE on their bundles as well.
        if (event.getEventType() == Event.CREATE
                || event.getEventType() == Event.DELETE)
        {
                return;
        }
       
        // Events of type ADD and REMOVE does currently (DSpace 4.1) not exist
        // on a bitstream
        log.warn("Got an unexpected event type (" + event.getEventTypeAsString()
                + ") for a bitstream. Ignoring.");
    }
   
    public void consumeBundles(Context ctx, Event event) throws SQLException
    {
        if (event.getEventType() == Event.ADD
                || event.getEventType() == Event.REMOVE
                || event.getEventType() == Event.MODIFY
                || event.getEventType() == Event.MODIFY_METADATA)
        {
            // either a Bitstream was added or removed or the Bundle was changed
            // update its item.
            Bundle bundle = Bundle.find(ctx, event.getSubjectID());
            if (bundle == null)
            {
                log.warn("Cannot find bundle " + event.getSubjectID() + "! "
                        + "Ignoring, as it is likely it was deleted "
                        + "and we'll cover it by a REMOVE event on its item.");
                return;
            }
            Item[] items = bundle.getItems();
            for (Item i : items)
            {
                DSOIdentifier id = new DSOIdentifier(i, ctx);
                if (!this.toDelete.contains(id) && !this.toConvert.contains(id))
                {
                    this.toConvert.addLast(id);
                }
            }
        }

        // ignore create and delete event on Bundles, as they should be
        // reported as ADD and REMOVE on their items as well.
        if (event.getEventType() == Event.CREATE
                || event.getEventType() == Event.DELETE)
        {
            return;
        }
       
        log.warn("Got an unexpected event type (" + event.getEventTypeAsString()
                + ") for a bundle. Ignoring.");
    }
   
    public void consumeCommunityCollectionItem(Context ctx, Event event) throws SQLException
    {
        if (event.getSubjectType() != Constants.COMMUNITY
                && event.getSubjectType() != Constants.COLLECTION
                && event.getSubjectType() != Constants.ITEM)
        {
            log.error("Called on an unexpected Event with subject type "
                    + event.getSubjectTypeAsString() + " and event type "
                    + event.getEventTypeAsString() + ", ignoring.");
            return;
        }
       
        if (event.getEventType() == Event.DELETE)
        {
            DSOIdentifier id = new DSOIdentifier(event.getSubjectType(),
                    event.getSubjectID(), event.getDetail(), event.getIdentifiers());
           
            if (this.toConvert.contains(id))
            {
                this.toConvert.remove(id);
            }
           
            if (!this.toDelete.contains(id))
            {
                this.toDelete.addLast(id);
            }
            return;
        }
       
        if (event.getEventType() == Event.MODIFY
                || event.getEventType() == Event.MODIFY_METADATA
                || event.getEventType() == Event.ADD
                || event.getEventType() == Event.REMOVE
                || event.getEventType() == Event.CREATE)
        {
            // we have to find the dso as the handle is set as detail only
            // if the event type is delete.
            DSpaceObject dso = event.getSubject(ctx);
            if (dso == null)
            {
                log.warn("Cannot find " + event.getSubjectTypeAsString() + " "
                        + event.getSubjectID() + "! " + "Ignoring, as it is "
                        + "likely it was deleted and we'll cover it by another "
                        + "event with the type REMOVE.");
                return;
            }
            DSOIdentifier id = new DSOIdentifier(dso, ctx);

            // If an item gets withdrawn, a MODIFIY event is fired. We have to
            // delete the item from the triple store instead of converting it.
            // we don't have to take care for reinstantions of items as they can
            // be processed as normal modify events.
            if (dso instanceof Item
                    && event.getDetail() != null
                    && event.getDetail().equals("WITHDRAW"))
            {
                if (this.toConvert.contains(id))
                {
                    this.toConvert.remove(id);
                }
                if (!this.toDelete.contains(id))
                {
                    this.toDelete.add(id);
                    return;
                }
            }

            if (!this.toDelete.contains(id)
                    && !this.toConvert.contains(id))
            {
                this.toConvert.addLast(id);
            }
        }
    }
   
    public void consumeSite(Context ctx, Event event)
    {
        // in case a top level community was added or remove.
        // event type remove won't be thrown until DS-1966 is fixed (f.e. by
        // merging PR #517).
        if (event.getEventType() == Event.ADD
                || event.getEventType() == Event.REMOVE)
        {
            DSOIdentifier id = new DSOIdentifier(Constants.SITE,
                    Site.SITE_ID, Site.getSiteHandle(), new String[] {Site.getSiteHandle()});
            if (!this.toConvert.contains(id)) this.toConvert.add(id);
            return;
        }
        log.warn("Got an unexpected Event for the SITE. Event type is "
                + event.getEventTypeAsString() + ", ignoring.");
    }

    @Override
    public void end(Context ctx) throws Exception {
        log.debug("Started processing of queued events.");
        // create a new context, to be sure to work as anonymous user
        // we don't want to store private data in a triplestore with public
        // SPARQL endpoint.
        ctx = new Context(Context.READ_ONLY);
        if (toDelete == null)
        {
            log.debug("Deletion queue does not exists, creating empty queue.");
            this.toDelete = new LinkedList<>();
        }
        if (toConvert != null)
        {
            log.debug("Starting conversion of DSpaceObjects.");
            while (true)
            {
                DSOIdentifier id;
                try { id = toConvert.removeFirst(); }
                catch (NoSuchElementException ex) { break; }

                if (toDelete.contains(id))
                {
                    log.debug("Skipping " + Constants.typeText[id.type] + " "
                            + Integer.toString(id.id) + " as it is marked for "
                            + "deletion as well.");
                    continue;
                }
                log.debug("Converting " + Constants.typeText[id.type] + " "
                            + Integer.toString(id.id) + ".");
                convert(ctx, id);
            }
            log.debug("Conversion ended.");
        }
        log.debug("Starting to delete data from the triple store...");
        while (true)
        {
            DSOIdentifier id;
            try { id = toDelete.removeFirst(); }
            catch (NoSuchElementException ex) { break; }
           
            log.debug("Going to delete data from " +
                    Constants.typeText[id.type] + " "
                    + Integer.toString(id.id) + ".");
            delete(ctx, id);
        }
        ctx.abort();
        log.debug("Deletion finished.");
    }

    void convert(Context ctx, DSOIdentifier id) throws SQLException
    {
        Model m = null;
        try
        {
            if (id.type == Constants.SITE)
            {
                m = RDFUtil.convertAndStore(ctx, Site.find(ctx, 0));
                return;
            }

            DSpaceObject dso = DSpaceObject.find(ctx, id.type, id.id);
            if (dso == null)
            {
                log.error("Cannot find " + Constants.typeText[id.type]
                        + " " + id.id + " unexpectedly! Will delete all "
                        + "information about it in the triple store.");
                toDelete.add(id);
                return;
            }
            m = RDFUtil.convertAndStore(ctx, dso);
        }
        catch(AuthorizeException ex)
        {
            log.debug(Constants.typeText[id.type] + " " +
                    Integer.toString(id.id) + " couldn't be converted: "
                    + "anonymous user doesn't have read permsission. "
                    + ex.getMessage());
            toDelete.add(id);
        }
        catch (IllegalArgumentException ex)
        {
            log.error("Ignoring an unexpected IllegalArgumentException: "
                    + ex.getMessage(), ex);
        }
        catch (ItemNotArchivedException ex)
        {
            log.info("Anonymous user cannot read "
                    + Constants.typeText[id.type] + " "
                    + Integer.toString(id.id)
                    + ": deleting it from the triplestore.");
            toDelete.add(id);
        }
        catch (ItemNotDiscoverableException ex)
        {
            log.info("Item " + Integer.toString(id.id) + " is not "
                    + "discoverable: deleting it from the triplestore.");
            toDelete.add(id);
        }
        catch (ItemWithdrawnException ex)
        {
            log.info("Item " + Integer.toString(id.id) + " is withdrawn: "
                    + "deleting it from the triplestore.");
            toDelete.add(id);
        }
        catch (RDFMissingIdentifierException ex)
        {
            log.warn("Cannot convert " + Constants.typeText[id.type]
                    + " " + Integer.toString(id.id) + ", as no RDF "
                    + "identifier could be generated: "
                    + ex.getMessage(), ex);
        }
        finally
        {
            if (m != null)
            {
                m.close();
            }
        }
    }
   
    void delete(Context context, DSOIdentifier id)
            throws SQLException {
        try
        {
            RDFUtil.delete(context, id.type, id.id, id.handle, id.identifiers);
        }
        catch (RDFMissingIdentifierException ex)
        {
            log.warn("Cannot delete " + Constants.typeText[id.type] + " "
                    + Integer.toString(id.id) + ": "
                    + ex.getMessage(), ex);
        }
    }
   
    @Override
    public void finish(Context ctx) throws Exception {
    }

    @Override
    public void initialize() throws Exception {
    }
   
    class DSOIdentifier
    {
        int type;
        int id;
        String handle;
        String[] identifiers;
       
        DSOIdentifier(int type, int id, String handle, String[] identifiers)
        {
            this.type = type;
            this.id = id;
            this.handle = handle;
            this.identifiers = identifiers;
        }
       
        DSOIdentifier(DSpaceObject dso, Context ctx)
        {
            if (dso.getType() != Constants.SITE
                    && dso.getType() != Constants.COMMUNITY
                    && dso.getType() != Constants.COLLECTION
                    && dso.getType() != Constants.ITEM)
            {
                throw new IllegalArgumentException("Provided DSpaceObject does"
                        + " not have a handle!");
            }
            this.type = dso.getType();
            this.id = dso.getID();
            this.handle = dso.getHandle();
            this.identifiers = dso.getIdentifiers(ctx);
        }
       
        @Override
        public boolean equals(Object o)
        {
            if (!(o instanceof DSOIdentifier)) return false;
            DSOIdentifier dsoId = (DSOIdentifier) o;
           
            /*
            log.warn("Testing if " + Constants.typeText[this.type] + " "
                    + Integer.toString(this.id) + " and "
                    + Constants.typeText[dsoId.type] + " "
                    + Integer.toString(dsoId.id) + " are equal.");
            */
            return (this.type == dsoId.type && this.id == dsoId.id);
        }
       
        @Override
        public int hashCode()
        {
            /* log.debug("Created hash " + Integer.toString(this.type + (10*this.id)));*/

            // as at least up to DSpace version 4.1 DSpaceObjectType is a
            // one-digit number, this should produce an distinct hash.
            return this.type + (10*this.id);
        }
    }
}
TOP

Related Classes of org.dspace.rdf.RDFConsumer$DSOIdentifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.