org.dspace.app.cris.batch.ScriptCrisSubscribe.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.app.cris.batch.ScriptCrisSubscribe.java

Source

/**
 * 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
 *
 * https://github.com/CILEA/dspace-cris/wiki/License
 */
/*
 * Subscribe.java
 *
 * Version: $Revision: 3762 $
 *
 * Date: $Date: 2009-05-07 06:36:47 +0200 (gio, 07 mag 2009) $
 *
 * Copyright (c) 2002-2009, The DSpace Foundation.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the DSpace Foundation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package org.dspace.app.cris.batch;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.mail.MessagingException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.dspace.app.cris.configuration.RelationConfiguration;
import org.dspace.app.cris.discovery.CrisSearchService;
import org.dspace.app.cris.integration.CrisComponentsService;
import org.dspace.app.cris.integration.ICRISComponent;
import org.dspace.app.cris.model.CrisConstants;
import org.dspace.app.cris.model.CrisSubscription;
import org.dspace.app.cris.service.ApplicationService;
import org.dspace.app.cris.util.Researcher;
import org.dspace.app.cris.util.ResearcherPageUtils;
import org.dspace.content.DCValue;
import org.dspace.content.Item;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.dspace.core.LogManager;
import org.dspace.discovery.SearchServiceException;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Subscribe;
import org.dspace.handle.HandleManager;

/**
 * Class defining methods for sending new item e-mail alerts to users. Based on
 * {@link Subscribe} written by Robert Tansley
 * 
 * @author pascarelli
 */
public class ScriptCrisSubscribe {
    /** log4j logger */
    private static Logger log = Logger.getLogger(ScriptCrisSubscribe.class);

    private static Map<Integer, List<String>> mapRelationFields = new HashMap<Integer, List<String>>();

    /**
     * Process subscriptions. This must be invoked only once a day. Messages are
     * only sent out when a rp has actually received new items, so that people's
     * mailboxes are not clogged with many "no new items" mails.
     * <P>
     * Yesterday's newly available items are included. If this is run at for
     * example midday, any items that have been made available during the
     * current day will not be included, but will be included in the next day's
     * run.
     * <P>
     * For example, if today's date is 2002-10-10 (in UTC) items made available
     * during 2002-10-09 (UTC) will be included.
     * 
     * @param applicationService
     * 
     * @param context
     *            DSpace context object
     * @param test
     * @throws SearchServiceException
     */
    public static void processDaily(Researcher researcher, ApplicationService applicationService, Context context,
            boolean test) throws SQLException, IOException, SearchServiceException {

        List<CrisSubscription> rpSubscriptions = applicationService.getList(CrisSubscription.class);
        EPerson currentEPerson = null;
        List<String> rpkeys = null; // List of rp keys
        List<String> relationField = new LinkedList<String>();
        for (CrisSubscription rpSubscription : rpSubscriptions) {
            // Does this row relate to the same e-person as the last?
            if ((currentEPerson == null) || (rpSubscription.getEpersonID() != currentEPerson.getID())) {
                // New e-person. Send mail for previous e-person
                if (currentEPerson != null) {
                    try {
                        relationField = mapRelationFields.get(rpSubscription.getTypeDef());
                        sendEmail(researcher, context, currentEPerson, rpkeys, test, relationField);
                    } catch (MessagingException me) {
                        log.error("Failed to send subscription to eperson_id=" + currentEPerson.getID());
                        log.error(me);
                    }
                }

                currentEPerson = EPerson.find(context, rpSubscription.getEpersonID());
                rpkeys = new ArrayList<String>();
            }
            rpkeys.add(ResearcherPageUtils
                    .getPersistentIdentifier(applicationService.getEntityByUUID(rpSubscription.getUuid())));
        }
        // Process the last person
        if (currentEPerson != null) {
            try {
                sendEmail(researcher, context, currentEPerson, rpkeys, test, relationField);
            } catch (MessagingException me) {
                log.error("Failed to send subscription to eperson_id=" + currentEPerson.getID());
                log.error(me);
            }
        }
    }

    /**
     * Sends an email to the given e-person with details of new items in the
     * given dspace object (MUST be a community or a collection), items that
     * appeared yesterday. No e-mail is sent if there aren't any new items in
     * any of the dspace objects.
     * 
     * @param context
     *            DSpace context object
     * @param eperson
     *            eperson to send to
     * @param rpkeys
     *            List of DSpace Objects
     * @param test
     * @throws SearchServiceException
     */
    public static void sendEmail(Researcher researcher, Context context, EPerson eperson, List<String> rpkeys,
            boolean test, List<String> relationFields)
            throws IOException, MessagingException, SQLException, SearchServiceException {

        CrisSearchService searchService = researcher.getCrisSearchService();

        // Get a resource bundle according to the eperson language preferences
        Locale supportedLocale = I18nUtil.getEPersonLocale(eperson);

        StringBuffer emailText = new StringBuffer();
        boolean isFirst = true;

        for (String rpkey : rpkeys) {
            SolrQuery query = new SolrQuery();
            query.setFields("search.resourceid");
            query.addFilterQuery("{!field f=search.resourcetype}" + Constants.ITEM, "{!field f=inarchive}true");

            for (String tmpRelations : relationFields) {
                String fq = "{!field f=" + tmpRelations + "}" + rpkey;
                query.addFilterQuery(fq);
            }

            query.setRows(Integer.MAX_VALUE);

            if (ConfigurationManager.getBooleanProperty("eperson.subscription.onlynew", false)) {
                // get only the items archived yesterday
                query.setQuery("dateaccessioned:(NOW/DAY-1DAY)");
            } else {
                // get all item modified yesterday but not published the day
                // before
                // and all the item modified today and archived yesterday
                query.setQuery(
                        "(item.lastmodified:(NOW/DAY-1DAY) AND dateaccessioned:(NOW/DAY-1DAY)) OR ((item.lastmodified:(NOW/DAY) AND dateaccessioned:(NOW/DAY-1DAY)))");
            }

            QueryResponse qResponse = searchService.search(query);
            SolrDocumentList results = qResponse.getResults();

            // Only add to buffer if there are new items
            if (results.getNumFound() > 0)

            {
                if (!isFirst) {
                    emailText.append("\n---------------------------------------\n");
                } else {
                    isFirst = false;
                }

                emailText.append(I18nUtil.getMessage("org.dspace.eperson.Subscribe.new-items", supportedLocale))
                        .append(" ").append(rpkey).append(": ").append(results.getNumFound()).append("\n\n");

                for (SolrDocument solrDoc : results)

                {
                    Item item = Item.find(context, (Integer) solrDoc.getFieldValue("search.resourceid"));

                    DCValue[] titles = item.getDC("title", null, Item.ANY);
                    emailText.append("      ")
                            .append(I18nUtil.getMessage("org.dspace.eperson.Subscribe.title", supportedLocale))
                            .append(" ");

                    if (titles.length > 0) {
                        emailText.append(titles[0].value);
                    } else {
                        emailText.append(
                                I18nUtil.getMessage("org.dspace.eperson.Subscribe.untitled", supportedLocale));
                    }

                    DCValue[] authors = item.getDC("contributor", Item.ANY, Item.ANY);

                    if (authors.length > 0) {
                        emailText.append("\n    ").append(
                                I18nUtil.getMessage("org.dspace.eperson.Subscribe.authors", supportedLocale))
                                .append(" ").append(authors[0].value);

                        for (int k = 1; k < authors.length; k++) {
                            emailText.append("\n             ").append(authors[k].value);
                        }
                    }

                    emailText.append("\n         ")
                            .append(I18nUtil.getMessage("org.dspace.eperson.Subscribe.id", supportedLocale))
                            .append(" ").append(HandleManager.getCanonicalForm(item.getHandle())).append("\n\n");
                    context.removeCached(item, item.getID());
                }
            }
        }

        // Send an e-mail if there were any new items
        if (emailText.length() > 0) {

            if (test) {
                log.info(LogManager.getHeader(context, "subscription:", "eperson=" + eperson.getEmail()));
                log.info(LogManager.getHeader(context, "subscription:", "text=" + emailText.toString()));

            } else {

                Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "subscription"));
                email.addRecipient(eperson.getEmail());
                email.addArgument(emailText.toString());
                email.send();

                log.info(LogManager.getHeader(context, "sent_subscription", "eperson_id=" + eperson.getID()));

            }
        }
    }

    /**
     * Method for invoking subscriptions via the command line
     * 
     * @param argv
     *            command-line arguments, none used yet
     */
    public static void main(String[] argv) {
        log.info("#### START DELETE: -----" + new Date() + " ----- ####");
        String usage = "it.cilea.hku.authority.ScriptRPSubscribe [-t] or nothing to send out subscriptions.";

        Options options = new Options();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine line = null;

        {
            Option opt = new Option("t", "test", false, "Run test session");
            opt.setRequired(false);
            options.addOption(opt);
        }

        {
            Option opt = new Option("h", "help", false, "Print this help message");
            opt.setRequired(false);
            options.addOption(opt);
        }

        try {
            line = new PosixParser().parse(options, argv);
        } catch (Exception e) {
            // automatically generate the help statement
            formatter.printHelp(usage, e.getMessage(), options, "");
            System.exit(1);
        }

        if (line.hasOption("h")) {
            // automatically generate the help statement
            formatter.printHelp(usage, options);
            System.exit(1);
        }

        boolean test = line.hasOption("t");

        if (test)
            log.setLevel(Level.DEBUG);
        Context context = null;
        try {
            context = new Context();
            Researcher researcher = new Researcher();
            ApplicationService applicationService = researcher.getApplicationService();

            List<CrisComponentsService> serviceComponent = researcher.getAllCrisComponents();
            for (CrisComponentsService service : serviceComponent) {
                for (ICRISComponent component : service.getComponents().values()) {
                    RelationConfiguration relationConfiguration = component.getRelationConfiguration();
                    if (Item.class.isAssignableFrom(relationConfiguration.getRelationClass())) {
                        Integer key = CrisConstants.getEntityType(component.getTarget());
                        String query = relationConfiguration.getQuery();
                        if (!mapRelationFields.containsKey(key)) {
                            List<String> rels = new LinkedList<String>();
                            rels.add(query);
                            mapRelationFields.put(key, rels);
                        } else {
                            mapRelationFields.get(key).add(query);
                        }
                    }
                }
            }
            processDaily(researcher, applicationService, context, test);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (context != null && context.isValid()) {
                // Nothing is actually written
                context.abort();
            }
        }
        log.info("#### END: -----" + new Date() + " ----- ####");
        System.exit(0);
    }
}