org.dspace.app.cris.integration.RPAuthority.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.app.cris.integration.RPAuthority.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
 */
package org.dspace.app.cris.integration;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.dspace.app.cris.model.CrisConstants;
import org.dspace.app.cris.model.ResearcherPage;
import org.dspace.app.cris.model.RestrictedField;
import org.dspace.app.cris.model.VisibilityConstants;
import org.dspace.app.cris.service.ApplicationService;
import org.dspace.app.cris.service.RelationPreferenceService;
import org.dspace.app.cris.util.ResearcherPageUtils;
import org.dspace.content.DCPersonName;
import org.dspace.content.DSpaceObject;
import org.dspace.content.authority.AuthorityVariantsSupport;
import org.dspace.content.authority.Choice;
import org.dspace.content.authority.ChoiceAuthority;
import org.dspace.content.authority.Choices;
import org.dspace.content.authority.NotificableAuthority;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.SearchService;
import org.dspace.services.ConfigurationService;
import org.dspace.utils.DSpace;

/**
 * This class is the main point of integration beetween the Researcher Pages and
 * DSpace. It implements the contract of the Authority Control Framework
 * providing full support for the variants facility. It implements also the
 * callback interface to "record" rejection of potential matches.
 * 
 * @author cilea
 */
public class RPAuthority extends CRISAuthority implements AuthorityVariantsSupport, NotificableAuthority {
    /** The logger */
    private static Logger log = Logger.getLogger(RPAuthority.class);

    /** The name as this ChoiceAuthority MUST be configurated */
    public final static String RP_AUTHORITY_NAME = "RPAuthority";

    /** The RPs database service layer */
    private ApplicationService applicationService;

    /** The RPs search service layer */
    private SearchService searchService;

    private ConfigurationService configurationService;

    private RelationPreferenceService relationPreferenceService;

    /**
     * Make sure that the class is fully initialized before use it
     */
    private void init() {
        if (applicationService == null && searchService == null) {
            DSpace dspace = new DSpace();
            applicationService = dspace.getServiceManager().getServiceByName("applicationService",
                    ApplicationService.class);
            searchService = dspace.getServiceManager().getServiceByName("org.dspace.discovery.SearchService",
                    SearchService.class);

            configurationService = dspace.getServiceManager()
                    .getServiceByName("org.dspace.services.ConfigurationService", ConfigurationService.class);

            relationPreferenceService = dspace.getServiceManager().getServiceByName(
                    "org.dspace.app.cris.service.RelationPreferenceService", RelationPreferenceService.class);
        }
    }

    /**
     * Empty constructor needed by the DSpace plugin facility.
     */
    public RPAuthority() {
        // nothing to do, initialization is provided by the IoC Spring Frameword
    }

    /**
     * Return a list of choices performing a lucene query on the RPs names index
     * appending the wildchar to every word in the query (i.e. if the query
     * string is Chan Tse the search will be perfomed with Chan* Tse*). For any
     * matching RP will be returned choices for every variants form.
     * 
     * {@link ChoiceAuthority#getMatches(String, int, int, int, String)}
     * 
     * @param query
     *            the lookup string
     * @param collection
     *            (not used by this Authority)
     * @param locale
     *            (not used by this Authority)
     * @param start
     *            (not used by this Authority)
     * @param limit
     *            (not used by this Authority)
     * @param locale
     *            (not used by this Authority)
     * 
     * @return a Choices of RPs where a name form match the query string
     */
    @Override
    public Choices getMatches(String field, String query, int collection, int start, int limit, String locale) {
        try {
            init();
            if (query != null && query.length() > 2) {
                DCPersonName tmpPersonName = new DCPersonName(query.toLowerCase());

                String luceneQuery = "";
                if (StringUtils.isNotBlank(tmpPersonName.getLastName())) {
                    luceneQuery += ClientUtils.escapeQueryChars(tmpPersonName.getLastName().trim())
                            + (StringUtils.isNotBlank(tmpPersonName.getFirstNames()) ? "" : "*");
                }

                if (StringUtils.isNotBlank(tmpPersonName.getFirstNames())) {
                    luceneQuery += (luceneQuery.length() > 0 ? " " : "")
                            + ClientUtils.escapeQueryChars(tmpPersonName.getFirstNames().trim()) + "*";
                }
                luceneQuery = luceneQuery.replaceAll("\\\\ ", " ");
                DiscoverQuery discoverQuery = new DiscoverQuery();
                discoverQuery.setDSpaceObjectFilter(CrisConstants.RP_TYPE_ID);
                String filter = configurationService.getProperty("cris." + RP_AUTHORITY_NAME
                        + ((field != null && !field.isEmpty()) ? "." + field : "") + ".filter");
                if (filter != null) {
                    discoverQuery.addFilterQueries(filter);
                }

                discoverQuery.setQuery("{!lucene q.op=AND df=crisauthoritylookup}(" + luceneQuery + ") OR (\""
                        + luceneQuery.substring(0, luceneQuery.length() - 1) + "\")");
                discoverQuery.setMaxResults(50);
                DiscoverResult result = searchService.search(null, discoverQuery, true);

                List<Choice> choiceList = new ArrayList<Choice>();

                for (DSpaceObject dso : result.getDspaceObjects()) {
                    ResearcherPage rp = (ResearcherPage) dso;
                    choiceList.add(new Choice(ResearcherPageUtils.getPersistentIdentifier(rp), rp.getFullName(),
                            ResearcherPageUtils.getLabel(rp.getFullName(), rp)));

                    if (rp.getTranslatedName() != null
                            && rp.getTranslatedName().getVisibility() == VisibilityConstants.PUBLIC
                            && rp.getTranslatedName().getValue() != null) {
                        choiceList.add(new Choice(ResearcherPageUtils.getPersistentIdentifier(rp),
                                rp.getTranslatedName().getValue(),
                                ResearcherPageUtils.getLabel(rp.getTranslatedName().getValue(), rp)));
                    }

                    for (RestrictedField variant : rp.getVariants()) {
                        if (variant.getValue() != null && variant.getVisibility() == VisibilityConstants.PUBLIC) {
                            choiceList.add(new Choice(ResearcherPageUtils.getPersistentIdentifier(rp),
                                    variant.getValue(), ResearcherPageUtils.getLabel(variant.getValue(), rp)));
                        }
                    }
                }

                Choice[] results = new Choice[choiceList.size()];
                results = choiceList.toArray(results);
                return new Choices(results, 0, results.length, Choices.CF_AMBIGUOUS, false, 0);
            }
            return new Choices(false);
        } catch (Exception e) {
            log.error("Error quering the RPAuthority - " + e.getMessage(), e);
            return new Choices(true);
        }
    }

    /**
     * Return a list of choices performing an exact query on the RP names (full,
     * Chinese, academinc, variants). For any matching RP will be returned
     * choices for every variants form, the default choice will be which that
     * match with the "query" string. This method is used by unattended
     * submssion only, interactive submission will use the
     * {@link RPAuthority#getMatches(String, String, int, int, int, String)}.
     * The confidence value of the returned Choices will be
     * {@link Choices#CF_UNCERTAIN} if there is only a RP that match with the
     * lookup string or {@link Choices#CF_AMBIGUOUS} if there are more RPs.
     * 
     * {@link ChoiceAuthority#getMatches(String, String, int, int, int, String)}
     * 
     * @param field
     *            (not used by this Authority)
     * @param text
     *            the lookup string
     * @param collection
     *            (not used by this Authority)
     * @param locale
     *            (not used by this Authority)
     * @return a Choices of RPs that have an exact string match between a name
     *         forms and the text lookup string
     */
    @Override
    public Choices getBestMatch(String field, String text, int collection, String locale) {

        try {
            init();
            List<Choice> choiceList = new ArrayList<Choice>();
            int totalResult = 0;
            if (text != null && text.length() > 2) {
                DiscoverQuery discoverQuery = new DiscoverQuery();
                discoverQuery.setDSpaceObjectFilter(CrisConstants.RP_TYPE_ID);
                String filter = configurationService.getProperty("cris." + RP_AUTHORITY_NAME + ".filter");
                if (filter != null) {
                    discoverQuery.addFilterQueries(filter);
                }

                discoverQuery.setQuery("{!lucene q.op=AND df=crisauthoritylookup}\""
                        + ClientUtils.escapeQueryChars(text.trim()) + "\"");
                discoverQuery.setMaxResults(50);
                DiscoverResult result = searchService.search(null, discoverQuery, true);
                totalResult = (int) result.getTotalSearchResults();
                for (DSpaceObject dso : result.getDspaceObjects()) {
                    ResearcherPage rp = (ResearcherPage) dso;
                    choiceList.add(
                            new Choice(rp.getCrisID(), text, ResearcherPageUtils.getLabel(rp.getFullName(), rp)));
                }
            }

            Choice[] results = new Choice[choiceList.size()];
            if (choiceList.size() > 0) {
                results = choiceList.toArray(results);

                if (totalResult == 1) {
                    return new Choices(results, 0, totalResult, Choices.CF_UNCERTAIN, false, 0);
                } else {
                    return new Choices(results, 0, totalResult, Choices.CF_AMBIGUOUS, false, 0);
                }
            } else {
                return new Choices(false);
            }
        } catch (Exception e) {
            log.error("Error quering the HKUAuthority - " + e.getMessage(), e);
            return new Choices(true);
        }
    }

    /**
     * Return a list of all not null "public" forms of the RP name.
     * 
     * @param key
     *            the researcher identifier (i.e. rp00024)
     * @param locale
     *            (not used by this Authority)
     * 
     * @return a list of all not null "public" forms of the RP name.
     */
    public List<String> getVariants(String key, String locale) {
        init();
        Integer id = ResearcherPageUtils.getRealPersistentIdentifier(key, ResearcherPage.class);
        if (id == null) {
            log.error(LogManager.getHeader(null, "getLabel", "invalid key for hkuauthority key " + key));
            return null;
        }
        ResearcherPage rp = applicationService.get(ResearcherPage.class, id);
        List<String> publicNames = new ArrayList<String>();
        publicNames.add(rp.getFullName());
        if (rp.getTranslatedName() != null
                && rp.getTranslatedName().getVisibility() == VisibilityConstants.PUBLIC) {
            String value = rp.getTranslatedName().getValue();
            if (StringUtils.isNotBlank(value)) {
                publicNames.add(value);
            }
        }

        if (rp.getPreferredName() != null && rp.getPreferredName().getVisibility() == VisibilityConstants.PUBLIC) {
            String value = rp.getPreferredName().getValue();
            if (StringUtils.isNotBlank(value)) {
                publicNames.add(value);
            }
        }

        List<RestrictedField> variants = rp.getVariants();
        if (variants != null) {
            for (RestrictedField v : variants) {
                if (v.getVisibility() == VisibilityConstants.PUBLIC) {
                    String value = v.getValue();
                    if (StringUtils.isNotBlank(value)) {
                        publicNames.add(value);
                    }
                }
            }
        }

        return publicNames;
    }

    /**
     * Record the reject of a potential match so to avoid the same proposal to
     * happen in future.
     * 
     * @param itemID
     *            the id of the item that has been rejected
     * @param authorityKey
     *            the researcher identifier (i.e. rp00024)
     */
    public void reject(int itemID, String authorityKey) {
        init();
        ResearcherPage cris = applicationService.getResearcherByAuthorityKey(authorityKey);
        Context context = null;

        try {
            context = new Context();
            context.turnOffAuthorisationSystem();
            List<String> list = new ArrayList<String>();
            list.add(String.valueOf(itemID));
            relationPreferenceService.unlink(context, cris, "publications", list);
            context.restoreAuthSystemState();
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (context != null && context.isValid()) {
                context.abort();
            }
        }

    }

    /**
     * Record the reject of a potential match so to avoid the same proposal to
     * happen in future.
     * 
     * @param itemIDs
     *            the id of the items that has been rejected
     * @param authorityKey
     *            the researcher identifier (i.e. rp00024)
     */
    public void reject(int[] itemIDs, String authorityKey) {
        init();
        ResearcherPage cris = applicationService.getResearcherByAuthorityKey(authorityKey);
        Context context = null;
        try {
            context = new Context();
            context.turnOffAuthorisationSystem();
            List<String> list = new ArrayList<String>();
            for (int itemID : itemIDs) {
                list.add(String.valueOf(itemID));
            }

            relationPreferenceService.unlink(context, cris, "publications", list);
            context.restoreAuthSystemState();
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (context != null && context.isValid()) {
                context.abort();
            }
        }

    }

    @Override
    protected int getCRISTargetTypeID() {
        return CrisConstants.RP_TYPE_ID;
    }

    @Override
    protected Class<ResearcherPage> getCRISTargetClass() {
        return ResearcherPage.class;
    }
}