All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dspace.autoversioning.AutoVersioningServiceImpl Maven / Gradle / Ivy

There is a newer version: 5.4.2
Show newest version
/**
 * 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.autoversioning;

import com.google.common.base.Throwables;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.*;
import org.dspace.content.packager.PackageIngester;
import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.PluginManager;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.utils.DSpace;
import org.dspace.versioning.Version;
import org.dspace.versioning.VersionHistory;
import org.dspace.versioning.VersioningService;
import org.springframework.beans.factory.annotation.Required;

import java.io.*;
import java.sql.SQLException;
import java.util.Date;

/**
 *
 *
 * @author Fabio Bolognesi (fabio at atmire dot com)
 * @author Mark Diggory (markd at atmire dot com)
 * @author Ben Bosman (ben at atmire dot com)
 */
public class AutoVersioningServiceImpl implements AutoVersioningService {

    private static final String AIP_PACKAGE_TYPE = "INTERNAL-AIP";
    /** log4j category */

    private static final Logger log = Logger.getLogger(AutoVersioningServiceImpl.class);

    private AutoVersionHistoryDAO versionHistoryDAO;
    private AutoVersionDAO versionDAO;
    private DefaultItemAutoVersionProvider provider;


    /** Service Methods */
//    public Version createNewVersion(Context c, int itemId){
//        return createNewVersion(c, itemId);
//    }


    public AutoVersion createNewWorkingVersionInSubmission(Context c, int itemId, String summary) {
        try{
            Item item = Item.find(c, itemId);

            Date date = new Date();
            if(item==null)
            {
                AutoVersionHistory history = findAutoVersionHistory(c, itemId);
                item = history.getLatestVersion().getItem();

                }

            // Create new Workspace Item
            Item itemNew = provider.createNewItemAndAddItInWorkspace(c, item);

            // Complete any update of the Item and new Identifier generation that needs to happen
            provider.updateItemState(c, itemNew, item);

            AutoVersion version = this.updateVersionHistory(c, itemNew, item, summary,"create new version in submission", date);

            return version;
        }catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @Override
    public Version createNewVersion(Context c, int itemId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Version createNewVersion(Context c, int itemId, String summary) {
        throw new UnsupportedOperationException();
    }

    public void removeVersion(Context c, int versionID) {
        AutoVersion version = versionDAO.find(c, versionID);
        if(version!=null){
            removeVersion(c, version);
        }
    }

    public void removeVersion(Context c, Item item) {
        // Commented out because we do NOT want to delete the latest version
        // which is called from Item.delete();
        /*Version version = versionDAO.findByItem(c, item);
        if(version!=null){
            removeVersion(c, version);
        }*/
    }

    @Override
    public Version getVersion(Context c, int versionID) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Version restoreVersion(Context c, int versionID) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Version restoreVersion(Context c, int versionID, String summary) {
        throw new UnsupportedOperationException();
    }

    @Override
    public VersionHistory findVersionHistory(Context c, int itemId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Version updateVersion(Context c, int itemId, String summary) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Version getVersion(Context c, Item item) {
        return (Version) versionDAO.findByItemId(c, item.getID());
    }

    protected void removeVersion(Context c, AutoVersion version) {
        try{
            AutoVersionHistory history = versionHistoryDAO.findById(c, version.getVersionHistoryID(), versionDAO);
            provider.deleteVersionedItem(c, version, history);
            versionDAO.delete(c, version.getVersionId());

            history.remove(version);

            if(history.isEmpty()){
                versionHistoryDAO.delete(c, version.getVersionHistoryID(), versionDAO);
            }

            Bitstream bit = version.getAIPBitstream();

            if(bit != null)
            {
                BitstreamUtil.delete(bit);
            }

        }catch (Exception e) {
            c.abort();
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public AutoVersionHistory findVersionByHistoryId(Context c, int versionHistoryId) {
        try{
            AutoVersionHistory history = versionHistoryDAO.findById(c,versionHistoryId, versionDAO);
            return history;
        }catch (Exception e) {
            c.abort();
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public AutoVersion getAutoVersion(Context c, int versionID) {
        return versionDAO.find(c, versionID);
    }


    public Item restoreAutoVersion(Context c, int versionID){
        return restoreAutoVersion(c, versionID, null);
    }

    public Item restoreAutoVersion(Context c, int versionID, String summary)  {
        AutoVersioningService versioningService = (AutoVersioningService) new DSpace().getSingletonService(VersioningService.class);
        AutoVersion version = versioningService.getAutoVersion(c,versionID);
        AutoVersionHistory versionHistory = versioningService.findVersionByHistoryId(c,version.getVersionHistoryID());
        Bitstream bitstream = version.getAIPBitstream();
        Item newItem = version.getItem();
        if(bitstream!=null)
        {
            AutoVersion latestVersionversion = versionHistory.getLatestVersion();
            Item itemToReplace = latestVersionversion.getItem();
            {
                PackageIngester sip = (PackageIngester) PluginManager
                        .getNamedPlugin(PackageIngester.class, AIP_PACKAGE_TYPE);
                if (sip == null) {
                    throw new RuntimeException("No PackageIngester configured with type " + AIP_PACKAGE_TYPE);
                }

                File sourceFile = null;

                try {
                    sourceFile = File.createTempFile("tmpversion_" + version.getVersionId() + "_sis", null);
                    PackageParameters pkgParams =new PackageParameters();
                    InputStream inputStream =bitstream.retrieve();
                    OutputStream outputStream = null;
                    try {
                        outputStream = new FileOutputStream(sourceFile);
                        IOUtils.copy(inputStream, outputStream);
                    } finally {
                        IOUtils.closeQuietly(inputStream);
                        IOUtils.closeQuietly(outputStream);
                    }

                    pkgParams.setProperty("manifestOnly","true");
                    pkgParams.setProperty("internal","true");
                    pkgParams.setProperty("restoreMode", "true");
                    newItem = (Item)sip.replace(c, itemToReplace, sourceFile, pkgParams);
                } catch (Exception e) {
                    c.abort();
                    Throwables.propagate(e);
                } finally {
                    sourceFile.delete();
                }
            }
        }
        return newItem;
    }

    public AutoVersionHistory findAutoVersionHistory(Context c, int itemId){
        return versionHistoryDAO.find(c, itemId, versionDAO);
    }

    public AutoVersion updateAutoVersion(Context c, int itemId, String summary) {
        AutoVersionImpl version = versionDAO.findByItemId(c, itemId);
        version.setSummary(summary);
        versionDAO.update(version);
        return version;
    }
    public AutoVersion updateVersionByVersionId(Context c, int itemId, int versionId, String summary) {
        AutoVersionImpl version = versionDAO.find(c,versionId);
        version.setSummary(summary);
        versionDAO.update(version);
        return version;
    }

    public AutoVersion getAutoVersion(Context c, Item item){
        return versionDAO.findByItemId(c, item.getID());
    }

    /**
     * Update version history will be called when
     * a.) Manually Created New Revision is added to submitters Workspace (version number = -1)
     * b.) Consumer generates new revision (version number = latest +1)
     * c.) InstallItem Creates New Version Record (new Item submitted from Workspace)
     *
     * @param c
     * @param item
     * @param summary
     * @param date
     */
    public AutoVersionImpl updateVersionHistory(Context c, Item item, String summary, String log, Date date) {
        return updateVersionHistory(c, item, null, null, summary, log ,date,false);
    }
    public AutoVersionImpl updateVersionHistory(Context c, Item item, int versionId, String summary, String log, Date date) {
        return updateVersionHistory(c, item, null, versionId, summary, log ,date,false);
    }
    public AutoVersionImpl updateVersionHistory(Context c, Item item, String summary, String log, Date date, boolean restoreMod) {
        return updateVersionHistory(c, item, null, null, summary, log ,date,restoreMod);
    }
    public AutoVersionImpl updateVersionHistory(Context c, Item newItem, Item previousItem, String summary, String log, Date date) {
        return updateVersionHistory( c, newItem, previousItem, null, summary, log,  date,false);
    }
    public AutoVersionImpl updateVersionHistory(Context c, Item newItem, Item previousItem, Integer versionId, String summary, String log, Date date, boolean restoreMode) {
        AutoVersionImpl versionImpl=null;
        try {

            AutoVersionHistory history = null;
            if (versionId != null) {
                AutoVersion version = versionDAO.find(c, versionId);
                history = versionHistoryDAO.findById(c, version.getVersionHistoryID(), versionDAO);
            } else {
                history = findAutoVersionHistory(c, newItem.getID());
            }

            if(history==null && previousItem != null)
            {
                history = findAutoVersionHistory(c, previousItem.getID());

                if(history == null)      {
                    AutoVersion origVersion =  updateVersionHistory(c, previousItem, "Original Version", "",date);
                    history = findAutoVersionHistory(c, previousItem.getID());
        }
    }

            if(history==null)
            {
                history = versionHistoryDAO.create(c);
            }

            // findByItem should return the either
            // (a) No version because it does not yet exist
            // (b) latest Version in history with same item id (should always be just one)
            // (c) the only working Version for this item (version number = -1)
            versionImpl = versionDAO.findByItem(c,newItem);

            //if there is no version or it's not a working version or it is a restore mode, create a new version
            if(versionImpl == null||versionImpl.getVersionNumber()!=-1||restoreMode)
            {
                // if version item is null , create a new version for the item
                // A submission or workflow Item is neither archived nor withdrawn
                // if so, its a "working version", create and assign -1 to version
                // If this is a deleted item being restored (known by presence of versionId parameter)
                // Create new version with incremented ID
                if (versionId==null) {
                    versionImpl = versionDAO.create(c, newItem.getID(), !newItem.isArchived() && !newItem.isWithdrawn());
                } else {
                    versionImpl = versionDAO.createWithVersionID(c, history);
    }
                versionImpl.setVersionDate(date);
                versionImpl.setEperson(newItem.getSubmitter());
                versionImpl.setItemID(newItem.getID());
                if(newItem.getHandle()!=null)
                    versionImpl.setHandle(newItem.getHandle());
                versionImpl.setSummary(summary);
                versionImpl.setVersionLog(log);
                if(restoreMode)
                {
                    versionImpl.setVersionNumber(-1);
                }
                history.add(versionImpl);
                versionImpl.setVersionHistory(history.getVersionHistoryId());
                versionDAO.update(versionImpl);
            }
            else
            {
                //it is a promotion action
                if(!newItem.isArchived() && !newItem.isWithdrawn())
                {
                    // If Item is in Workspace or Workflow, keep the version -1, don't write AIP yet
                    versionImpl.setVersionNumber(-1);
                    //versionImpl.setSummary("add new work space item");
                }
                else
                {
                    // If it is a working version that has been archived, get next number, write AIP
                    if(previousItem==null)
                    {
                        previousItem = history.getLatestVersion().getItem();
                    }
                    try{
                        if(previousItem!=null&&previousItem.getID()!=newItem.getID()){
                            // Keep the previous item around, but just mark it withdrawn.
                            // This is better than setting discoverable to false, as DataOne
                            // currently does:
                            // https://git.atmire.com/clients/dataone/blob/59ee28b8378f8037bc1eef292663dba125e7a2ca/dspace-dataone/dataone-api/src/main/java/org/dspace/versioning/VersioningServiceImpl.java#L340
                            // ..because it ensures this old version won't show up in Submissions.
                            previousItem.withdraw();
                        }
                    }catch (Exception e)
                    {
                        Throwables.propagate(e);
                    }
                    versionImpl.setVersionNumber(getNextVersionNumber(c, history));
                    //versionImpl.setSummary("archive new version");



                }

            }

            if(newItem.isArchived()
                    && !newItem.isWithdrawn()
                    && versionImpl.getAIPBitstream()==null
                    && !restoreMode){
                //the aip bitstream is null
                AIPManifestWriter aipManifestWriter = new AIPManifestWriter();
                Bitstream bitstream = aipManifestWriter.updateAIP(c,newItem,true);
                versionImpl.setAIPBitstream(bitstream.getID());
                AuthorizeManager.inheritPolicies(c, newItem, bitstream);

                OREManifestWriter oreManifestWriter = new OREManifestWriter();
                Bitstream b = oreManifestWriter.updateORE(c,newItem,versionImpl,true);
                versionImpl.setOREBitstream(b.getID());
                AuthorizeManager.inheritPolicies(c, newItem, b);

                AutoVersionDAO.addBitstreams(c,versionImpl.getVersionId(),newItem.getBundles());
            }
            if(summary!=null&&summary.length()>0&&(versionImpl.getSummary()==null||versionImpl.getSummary().length()==0))
            {
                //only update the version summary when it is empty
                versionImpl.setSummary(summary);
            }
            if(log!=null&&summary.length()>0&&(versionImpl.getVersionLog()==null||versionImpl.getVersionLog().length()==0))
            {
                //only update the version summary when it is empty
                versionImpl.setVersionLog(log);
            }
            if(newItem.getHandle()!=null)
                versionImpl.setHandle(newItem.getHandle());
            else if(previousItem != null && previousItem.getHandle()!=null)
            {
                versionImpl.setHandle(previousItem.getHandle());
            }
            versionDAO.update(versionImpl);

            return versionImpl;

        }catch (Exception e)
        {
            throw Throwables.propagate(e);
        }

    }


    protected int getNextVersionNumber(Context c, AutoVersionHistory vh) throws SQLException {
        // Tested on Postgres and Oracle
        // returns 1 if no version history exists
        // the maximum version number +1 elsewise.
        // do *NOT* add "WHERE item_id NOT NULL", as we use the version number
        // to create persistent identifier.
        TableRow row = DatabaseManager.querySingle(c,
                "SELECT (COALESCE(MAX(" + AutoVersionDAO.VERSION_NUMBER + "), 0) + 1)"
                        + " AS nextversionnumber FROM " + AutoVersionDAO.TABLE_NAME
                        + " WHERE " + AutoVersionDAO.HISTORY_ID + " = ?",
                vh.getVersionHistoryId());
        int next = row.getIntColumn("nextversionnumber");
        // check if we have uncommited versions in DSpace's cache
        if (vh.getLatestVersion() != null
                && vh.getLatestVersion().getVersionNumber() >= next) {
            log.debug("New version number: vh.getLatest....getVersionNumber... = "
                    + Integer.toString(vh.getLatestVersion().getVersionNumber() + 1));

        }

        return next;
    }

    public AutoVersionHistoryDAO getVersionHistoryDAO() {
        return versionHistoryDAO;
    }

    public void setVersionHistoryDAO(AutoVersionHistoryDAO versionHistoryDAO) {
        this.versionHistoryDAO = versionHistoryDAO;
    }

    public AutoVersionDAO getVersionDAO() {
        return versionDAO;
    }

    public void setVersionDAO(AutoVersionDAO versionDAO) {
        this.versionDAO = versionDAO;
    }

    @Required
    public void setProvider(DefaultItemAutoVersionProvider provider) {
        this.provider = provider;
    }


    public boolean canVersion(Context c, Item item){
        boolean canVersion = false;
        try{
            if(AuthorizeManager.isAdmin(c, item.getOwningCollection())||AuthorizeManager.authorizeActionBoolean(c,item, Constants.WRITE,false)||item.getSubmitter().equals(c.getCurrentUser()))
            {
                canVersion = true;
            }
            else
            {
                DSpaceObject parentObject = item.getParentObject();
                while(parentObject!=null&&parentObject.getType()!=Constants.SITE)
                {
                    if (parentObject.getType() == Constants.COLLECTION) {
                        if (AuthorizeManager.authorizeActionBoolean(c, parentObject, Constants.ADD)) {
                            canVersion = true;
                        }
                    }
                    //todo:add reviwers and editers check
                    parentObject = parentObject.getParentObject();
                }
            }
        }catch (Exception e)
        {
            throw Throwables.propagate(e);
        }
        return canVersion;
    }
    public void setVersionLog(AutoVersionImpl version, String versionLog){

        version.setVersionLog(versionLog);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy