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

org.dspace.xoai.util.ItemUtils Maven / Gradle / Ivy

The 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.xoai.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import com.lyncode.xoai.dataprovider.xml.xoai.Element;
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
import com.lyncode.xoai.util.Base64Utils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.util.factory.UtilServiceFactory;
import org.dspace.app.util.service.MetadataExposureService;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataValue;
import org.dspace.content.authority.Choices;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.RelationshipService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.Utils;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.xoai.data.DSpaceItem;

/**
 * @author Lyncode Development Team (dspace at lyncode dot com)
 */
@SuppressWarnings("deprecation")
public class ItemUtils {
    private static final Logger log = LogManager.getLogger(ItemUtils.class);

    private static final MetadataExposureService metadataExposureService
            = UtilServiceFactory.getInstance().getMetadataExposureService();

    private static final ItemService itemService
            = ContentServiceFactory.getInstance().getItemService();

    private static final RelationshipService relationshipService
            = ContentServiceFactory.getInstance().getRelationshipService();

    private static final BitstreamService bitstreamService
            = ContentServiceFactory.getInstance().getBitstreamService();

    private static final ConfigurationService configurationService
            = DSpaceServicesFactory.getInstance().getConfigurationService();

    private static final AuthorizeService authorizeService
            = AuthorizeServiceFactory.getInstance().getAuthorizeService();

    /**
     * Default constructor
     */
    private ItemUtils() {
    }

    public static Element getElement(List list, String name) {
        for (Element e : list) {
            if (name.equals(e.getName())) {
                return e;
            }
        }

        return null;
    }

    public static Element create(String name) {
        Element e = new Element();
        e.setName(name);
        return e;
    }

    public static Element.Field createValue(String name, String value) {
        Element.Field e = new Element.Field();
        e.setValue(value);
        e.setName(name);
        return e;
    }

    private static Element createBundlesElement(Context context, Item item) throws SQLException {
        Element bundles = create("bundles");

        List bs;

        bs = item.getBundles();
        for (Bundle b : bs) {
            Element bundle = create("bundle");
            bundles.getElement().add(bundle);
            bundle.getField().add(createValue("name", b.getName()));

            Element bitstreams = create("bitstreams");
            bundle.getElement().add(bitstreams);
            List bits = b.getBitstreams();
            for (Bitstream bit : bits) {
                // Check if bitstream is null and log the error
                if (bit == null) {
                    log.error("Null bitstream found, check item uuid: " + item.getID());
                    break;
                }
                boolean primary = false;
                // Check if current bitstream is in original bundle + 1 of the 2 following
                // Bitstream = primary bitstream in bundle -> true
                // No primary bitstream found in bundle-> only the first one gets flagged as "primary"
                if (b.getName() != null && b.getName().equals("ORIGINAL") && (b.getPrimaryBitstream() != null
                        && b.getPrimaryBitstream().getID() == bit.getID()
                        || b.getPrimaryBitstream() == null && bit.getID() == bits.get(0).getID())) {
                    primary = true;
                }

                Element bitstream = create("bitstream");
                bitstreams.getElement().add(bitstream);

                String baseUrl = configurationService.getProperty("oai.bitstream.baseUrl");
                String url = baseUrl + "/bitstreams/" + bit.getID().toString() + "/download";

                String cks = bit.getChecksum();
                String cka = bit.getChecksumAlgorithm();
                String oname = bit.getSource();
                String name = bit.getName();
                String description = bit.getDescription();

                if (name != null) {
                    bitstream.getField().add(createValue("name", name));
                }
                if (oname != null) {
                    bitstream.getField().add(createValue("originalName", name));
                }
                if (description != null) {
                    bitstream.getField().add(createValue("description", description));
                }
                // Add bitstream embargo information (READ policy present, for Anonymous group with a start date)
                addResourcePolicyInformation(context, bit, bitstream);

                bitstream.getField().add(createValue("format", bit.getFormat(context).getMIMEType()));
                bitstream.getField().add(createValue("size", "" + bit.getSizeBytes()));
                bitstream.getField().add(createValue("url", url));
                bitstream.getField().add(createValue("checksum", cks));
                bitstream.getField().add(createValue("checksumAlgorithm", cka));
                bitstream.getField().add(createValue("sid", bit.getSequenceID() + ""));
                // Add primary bitstream field to allow locating easily the primary bitstream information
                bitstream.getField().add(createValue("primary", primary + ""));
            }
        }

        return bundles;
    }

    /**
     * This method will add metadata information about associated resource policies for a give bitstream.
     * It will parse of relevant policies and add metadata information
     * @param context
     * @param bitstream the bitstream object
     * @param bitstreamEl the bitstream metadata object to add resource policy information to
     * @throws SQLException
     */
    private static void addResourcePolicyInformation(Context context, Bitstream bitstream, Element bitstreamEl)
            throws SQLException {
        // Pre-filter access policies by DSO (bitstream) and Action (READ)
        List policies = authorizeService.getPoliciesActionFilter(context, bitstream, Constants.READ);

        // Create resourcePolicies container
        Element resourcePolicies = create("resourcePolicies");

        for (ResourcePolicy policy : policies) {
            String groupName = policy.getGroup() != null ? policy.getGroup().getName() : null;
            String user = policy.getEPerson() != null ? policy.getEPerson().getName() : null;
            String action = Constants.actionText[policy.getAction()];
            Date startDate = policy.getStartDate();
            Date endDate = policy.getEndDate();

            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

            Element resourcePolicyEl = create("resourcePolicy");
            resourcePolicyEl.getField().add(createValue("group", groupName));
            resourcePolicyEl.getField().add(createValue("user", user));
            resourcePolicyEl.getField().add(createValue("action", action));
            if (startDate != null) {
                resourcePolicyEl.getField().add(createValue("start-date", formatter.format(startDate)));
            }
            if (endDate != null) {
                resourcePolicyEl.getField().add(createValue("end-date", formatter.format(endDate)));
            }
            // Add resourcePolicy to list of resourcePolicies
            resourcePolicies.getElement().add(resourcePolicyEl);
        }
        // Add list of resource policies to the corresponding Bitstream XML Element
        bitstreamEl.getElement().add(resourcePolicies);
    }

    private static Element createLicenseElement(Context context, Item item)
            throws SQLException, AuthorizeException, IOException {
        Element license = create("license");
        List licBundles;
        licBundles = itemService.getBundles(item, Constants.LICENSE_BUNDLE_NAME);
        if (!licBundles.isEmpty()) {
            Bundle licBundle = licBundles.get(0);
            List licBits = licBundle.getBitstreams();
            if (!licBits.isEmpty()) {
                Bitstream licBit = licBits.get(0);
                if (authorizeService.authorizeActionBoolean(context, licBit, Constants.READ)) {
                    InputStream in;

                    in = bitstreamService.retrieve(context, licBit);
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    Utils.bufferedCopy(in, out);
                    license.getField().add(createValue("bin", Base64Utils.encode(out.toString())));
                } else {
                    log.info("Missing READ rights for license bitstream. Did not include license bitstream for item: "
                            + item.getID() + ".");
                }
            }
        }
        return license;
    }

    /**
     * This method will add all sub-elements to a top element, like: dc, or dcterms, ...     *
     * @param schema         Element argument passed by reference that will be changed
     * @param val            Metadatavalue that will be processed
     * @throws SQLException
     */
    private static void fillSchemaElement(Element schema, MetadataValue val) throws SQLException {
        MetadataField field = val.getMetadataField();
        Element valueElem = schema;

        // Has element.. with XOAI one could have only schema and value
        if (field.getElement() != null && !field.getElement().equals("")) {
            Element element = getElement(schema.getElement(), field.getElement());
            if (element == null) {
                element = create(field.getElement());
                schema.getElement().add(element);
            }
            valueElem = element;

            // Qualified element?
            if (field.getQualifier() != null && !field.getQualifier().equals("")) {
                Element qualifier = getElement(element.getElement(), field.getQualifier());
                if (qualifier == null) {
                    qualifier = create(field.getQualifier());
                    element.getElement().add(qualifier);
                }
                valueElem = qualifier;
            }
        }

        // Language?
        if (val.getLanguage() != null && !val.getLanguage().equals("")) {
            Element language = getElement(valueElem.getElement(), val.getLanguage());
            if (language == null) {
                language = create(val.getLanguage());
                valueElem.getElement().add(language);
            }
            valueElem = language;
        } else {
            Element language = getElement(valueElem.getElement(), "none");
            if (language == null) {
                language = create("none");
                valueElem.getElement().add(language);
            }
            valueElem = language;
        }

        valueElem.getField().add(createValue("value", val.getValue()));
        if (val.getAuthority() != null) {
            valueElem.getField().add(createValue("authority", val.getAuthority()));
            if (val.getConfidence() != Choices.CF_NOVALUE) {
                valueElem.getField().add(createValue("confidence", val.getConfidence() + ""));
            }
        }
    }

    /**
     * Utility method to retrieve a structured XML in XOAI format
     * @param context
     * @param item
     * @return Structured XML Metadata in XOAI format
     */
    public static Metadata retrieveMetadata(Context context, Item item) {
        Metadata metadata;

        // read all metadata into Metadata Object
        metadata = new Metadata();

        List vals = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY);
        for (MetadataValue val : vals) {
            MetadataField field = val.getMetadataField();
            try {
                // Don't expose fields that are hidden by configuration
                if (metadataExposureService.isHidden(context, field.getMetadataSchema().getName(), field.getElement(),
                        field.getQualifier())) {
                    continue;
                }

                Element schema = getElement(metadata.getElement(), field.getMetadataSchema().getName());
                if (schema == null) {
                    schema = create(field.getMetadataSchema().getName());
                    metadata.getElement().add(schema);
                }

                fillSchemaElement(schema, val);
            } catch (SQLException se) {
                throw new RuntimeException(se);
            }
        }

        // Done! Metadata has been read!
        // Now adding bitstream info
        try {
            Element bundles = createBundlesElement(context, item);
            metadata.getElement().add(bundles);
        } catch (SQLException e) {
            log.warn(e.getMessage(), e);
        }

        // Other info
        Element other = create("others");

        other.getField().add(createValue("handle", item.getHandle()));
        other.getField().add(createValue("identifier", DSpaceItem.buildIdentifier(item.getHandle())));
        other.getField().add(createValue("lastModifyDate", item.getLastModified().toString()));
        metadata.getElement().add(other);

        // Repository Info
        Element repository = create("repository");
        repository.getField().add(createValue("url", configurationService.getProperty("dspace.ui.url")));
        repository.getField().add(createValue("name", configurationService.getProperty("dspace.name")));
        repository.getField().add(createValue("mail", configurationService.getProperty("mail.admin")));
        metadata.getElement().add(repository);

        // Licensing info
        try {
            Element license = createLicenseElement(context, item);
            metadata.getElement().add(license);
        } catch (AuthorizeException | IOException | SQLException e) {
            log.warn(e.getMessage(), e);
        }

        return metadata;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy