org.ambraproject.service.user.UserServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.service.user.UserServiceImpl.java

Source

/*
 * Copyright (c) 2007-2014 by Public Library of Science
 *
 * http://plos.org
 * http://ambraproject.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ambraproject.service.user;

import com.google.gson.Gson;
import org.ambraproject.configuration.ConfigurationStore;
import org.ambraproject.models.ArticleView;
import org.ambraproject.models.SavedSearch;
import org.ambraproject.models.SavedSearchQuery;
import org.ambraproject.models.SavedSearchType;
import org.ambraproject.models.UserLogin;
import org.ambraproject.models.UserOrcid;
import org.ambraproject.models.UserProfile;
import org.ambraproject.models.UserSearch;
import org.ambraproject.service.hibernate.HibernateServiceImpl;
import org.ambraproject.service.permission.PermissionsService;
import org.ambraproject.service.search.SearchParameters;
import org.ambraproject.util.Pair;
import org.ambraproject.util.TextUtils;
import org.ambraproject.views.OrcidAuthorization;
import org.ambraproject.views.SavedSearchView;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * Class to roll up web services that a user needs in Ambra. Rest of application should generally
 * use AmbraUser to
 *
 * @author Stephen Cheng
 * @author Joe Osowski
 */
public class UserServiceImpl extends HibernateServiceImpl implements UserService {
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    private static final String ALERTS_CATEGORIES_CATEGORY = "ambra.userAlerts.categories.category";
    private static final String ALERTS_WEEKLY = "ambra.userAlerts.weekly";
    private static final String ALERTS_MONTHLY = "ambra.userAlerts.monthly";
    private static final String SUBJECT_FILTER = "ambra.userAlerts.subjectFilter";

    private PermissionsService permissionsService;
    private Configuration configuration;
    private boolean advancedLogging = false;

    @Override
    @Transactional(rollbackFor = { Throwable.class })
    public UserProfile login(final String authId, final UserLogin loginInfo) {
        log.debug("logging in user with auth id {}", authId);
        UserProfile user = getUserByAuthId(authId);
        if (user != null && this.advancedLogging) {
            loginInfo.setUserProfileID(user.getID());
            hibernateTemplate.save(loginInfo);
        }
        return user;
    }

    @Override
    @Transactional(readOnly = true)
    public UserProfile getUserByAuthId(String authId) {
        log.debug("Attempting to find user with authID: {}", authId);
        try {
            return (UserProfile) hibernateTemplate.findByCriteria(
                    DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("authId", authId)), 0, 1)
                    .get(0);
        } catch (IndexOutOfBoundsException e) {
            log.warn("Didn't find user for authID: {}", authId);
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = { Throwable.class })
    public UserProfile updateProfile(final UserProfile userProfile) throws NoSuchUserException {
        //get the user by auth id
        UserProfile existingUser = getUserByAuthId(userProfile.getAuthId());
        if (existingUser == null) {
            throw new NoSuchUserException();
        }
        log.debug("Found a user with authID: {}, updating profile", userProfile.getAuthId());
        copyFields(userProfile, existingUser);
        hibernateTemplate.update(existingUser);
        return existingUser;
    }

    @Override
    @Transactional
    public UserProfile setAlerts(String userAuthId, List<String> monthlyAlerts, List<String> weeklyAlerts) {
        UserProfile user = getUserByAuthId(userAuthId);

        log.debug("updating alerts for user: {}; Montly alerts: {}; weekly alerts: {}", new Object[] {
                user.getDisplayName(), StringUtils.join(monthlyAlerts, ","), StringUtils.join(weeklyAlerts, ",") });
        List<String> allAlerts;

        if (monthlyAlerts != null && weeklyAlerts != null) {
            allAlerts = new ArrayList<String>(monthlyAlerts.size() + weeklyAlerts.size());
            allAlerts.addAll(getAlertsList(monthlyAlerts, UserProfile.MONTHLY_ALERT_SUFFIX));
            allAlerts.addAll(getAlertsList(weeklyAlerts, UserProfile.WEEKLY_ALERT_SUFFIX));
        } else if (monthlyAlerts != null) {
            allAlerts = new ArrayList<String>(monthlyAlerts.size());
            allAlerts.addAll(getAlertsList(monthlyAlerts, UserProfile.MONTHLY_ALERT_SUFFIX));
        } else if (weeklyAlerts != null) {
            allAlerts = new ArrayList<String>(weeklyAlerts.size());
            allAlerts.addAll(getAlertsList(weeklyAlerts, UserProfile.WEEKLY_ALERT_SUFFIX));
        } else {
            allAlerts = new ArrayList<String>(0);
        }
        user.setAlertsList(allAlerts);
        hibernateTemplate.update(user);
        return user;
    }

    @Override
    @Transactional
    public UserProfile setSavedSearchAlerts(String userAuthId, List<String> monthlyAlerts,
            List<String> weeklyAlerts, List<String> deleteAlerts) {
        UserProfile user = getUserByAuthId(userAuthId);

        log.debug("updating alerts for user: {}; Montly alerts: {}; weekly alerts: {}; delete alerts: {}",
                new Object[] { user.getDisplayName(), StringUtils.join(monthlyAlerts, ","),
                        StringUtils.join(weeklyAlerts, ","), StringUtils.join(deleteAlerts, ",") });
        List<SavedSearchView> searches = getSavedSearches(user.getID());

        Set<String> weeklyItems = new HashSet<String>(weeklyAlerts);
        Set<String> monthlyItems = new HashSet<String>(monthlyAlerts);
        Set<String> deleteItems = new HashSet<String>(deleteAlerts);

        for (SavedSearchView savedSearch : searches) {
            //This method should only change user defined search alerts, not journal alerts
            if (savedSearch.getSearchType() == SavedSearchType.USER_DEFINED) {
                String idstr = String.valueOf(savedSearch.getSavedSearchId());
                boolean delete = deleteItems.contains(idstr);
                if (delete) {
                    deleteSavedSearch(user.getID(), savedSearch.getSavedSearchId());
                } else {
                    boolean weekly = weeklyItems.contains(idstr);
                    boolean monthly = monthlyItems.contains(idstr);
                    if (weekly != savedSearch.getWeekly() || monthly != savedSearch.getMonthly()) {
                        updateSavedSearch(savedSearch.getSavedSearchId(), weekly, monthly);
                    }
                }
            }
        }
        return user;
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = { Throwable.class })
    public UserProfile setFilteredWeeklySearchAlert(Long userProfileId, String[] subjects, String journal) {
        SearchParameters searchParameters = new SearchParameters();

        searchParameters.setQuery("*:*");
        searchParameters.setFilterJournals(new String[] { journal });
        searchParameters.setFilterSubjectsDisjunction(subjects);

        //We store the saved search here as JSON instead of serializing the object cuz JSON rocks
        SavedSearchQuery query = saveSearchQuery(searchParameters);

        UserProfile user = getUser(userProfileId);
        SavedSearch newSearch = null;

        //See if a record exists already, we only allow one weekly alert of type JOURNAL_ALERT per journal
        //We key off of the title as it is not user facing
        for (SavedSearch savedSearch : user.getSavedSearches()) {
            if (savedSearch.getSearchType() == SavedSearchType.JOURNAL_ALERT && savedSearch.getWeekly()
                    && savedSearch.getSearchName().equals(journal)) {
                newSearch = savedSearch;
            }
        }

        if (newSearch == null) {
            newSearch = new SavedSearch(journal, query);
            newSearch.setSearchType(SavedSearchType.JOURNAL_ALERT);
            newSearch.setWeekly(true);
            newSearch.setMonthly(false);
            user.getSavedSearches().add(newSearch);
        } else {
            newSearch.setSearchQuery(query);
        }

        hibernateTemplate.save(user);

        return user;
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = { Throwable.class })
    public UserProfile removedFilteredWeeklySearchAlert(Long userProfileId, String journal) {
        UserProfile user = getUser(userProfileId);

        SavedSearch oldSearch = null;

        //We key off of the title as it is not user facing
        for (SavedSearch savedSearch : user.getSavedSearches()) {
            if (savedSearch.getSearchType() == SavedSearchType.JOURNAL_ALERT && savedSearch.getWeekly()
                    && savedSearch.getSearchName().equals(journal)) {

                oldSearch = savedSearch;
            }
        }

        if (oldSearch != null) {
            user.getSavedSearches().remove(oldSearch);
        }

        hibernateTemplate.save(user);

        return user;
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = { Throwable.class })
    @SuppressWarnings("unchecked")
    public void saveSearch(Long userProfileId, SearchParameters searchParameters, String name, boolean weekly,
            boolean monthly) {

        UserProfile user = hibernateTemplate.get(UserProfile.class, userProfileId);

        SavedSearchQuery query = saveSearchQuery(searchParameters);

        SavedSearch savedSearch = new SavedSearch(name, query);
        savedSearch.setSearchType(SavedSearchType.USER_DEFINED);
        savedSearch.setWeekly(weekly);
        savedSearch.setMonthly(monthly);

        user.getSavedSearches().add(savedSearch);

        hibernateTemplate.save(user);
    }

    /**
     * Check to see if a matching savedSearch exists already with the passed in parameters
     * if so, reuses that record
     *
     * @param searchParameters
     *
     * @return the savedQuery object
     */
    private SavedSearchQuery saveSearchQuery(SearchParameters searchParameters) {
        Gson gson = new Gson();

        //We store the saved search here as JSON instead of serializing the object.
        String searchParametersString = gson.toJson(searchParameters);
        String queryHash = TextUtils.createHash(searchParametersString);
        SavedSearchQuery query;

        //Check to see if a matching savedSearch exists already.
        List<SavedSearchQuery> queryList = (List<SavedSearchQuery>) hibernateTemplate.findByCriteria(
                DetachedCriteria.forClass(SavedSearchQuery.class).add(Restrictions.eq("hash", queryHash))
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY));

        if (queryList.size() == 0) {
            query = new SavedSearchQuery(searchParametersString, queryHash);
            hibernateTemplate.save(query);
        } else {
            //It does exist, lets not create a new record
            query = queryList.get(0);
        }

        return query;
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = { Throwable.class })
    public List<SavedSearchView> getSavedSearches(Long userProfileId) {
        UserProfile userProfile = (UserProfile) DataAccessUtils
                .uniqueResult(hibernateTemplate.findByCriteria(DetachedCriteria.forClass(UserProfile.class)
                        .add(Restrictions.eq("ID", userProfileId)).setFetchMode("savedSearches", FetchMode.JOIN)
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));

        List<SavedSearch> searches = userProfile.getSavedSearches();
        List<SavedSearchView> searchViews = new ArrayList<SavedSearchView>(searches.size());

        for (SavedSearch savedSearch : searches) {
            searchViews.add(new SavedSearchView(savedSearch));
        }

        return searchViews;
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = { Throwable.class })
    public void deleteSavedSearch(Long userProfileId, Long savedSearchId) {

        UserProfile userProfile = (UserProfile) DataAccessUtils
                .uniqueResult(hibernateTemplate.findByCriteria(DetachedCriteria.forClass(UserProfile.class)
                        .add(Restrictions.eq("ID", userProfileId)).setFetchMode("savedSearches", FetchMode.JOIN)
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));
        List<SavedSearch> savedSearches = userProfile.getSavedSearches();
        for (Iterator<SavedSearch> it = savedSearches.iterator(); it.hasNext();) {
            SavedSearch savedSearch = it.next();
            if (savedSearch.getID().equals(savedSearchId)) {
                it.remove();
            }
        }
        hibernateTemplate.update(userProfile);
    }

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor = { Throwable.class })
    public void updateSavedSearch(Long savedSearchId, boolean weekly, boolean monthly) {
        SavedSearch savedSearch = hibernateTemplate.get(SavedSearch.class, savedSearchId);

        savedSearch.setMonthly(monthly);
        savedSearch.setWeekly(weekly);

        hibernateTemplate.update(savedSearch);
    }

    /**
     * return a list of alerts strings with the given suffix added, if they don't already have it
     *
     * @param alerts the list of alerts
     * @param suffix the alerts suffix
     * @return a list of alerts strings with the given suffix added, if they don't already have it
     */
    private List<String> getAlertsList(List<String> alerts, String suffix) {
        List<String> result = new ArrayList<String>(alerts.size());
        for (String alert : alerts) {
            if (alert.endsWith(suffix)) {
                result.add(alert);
            } else {
                result.add(alert + suffix);
            }
        }
        return result;
    }

    @Override
    @Transactional(readOnly = true)
    public UserProfile getUser(Long userId) {
        if (userId != null) {
            log.debug("Looking up user with id: {}", userId);
            return (UserProfile) hibernateTemplate.get(UserProfile.class, userId);
        } else {
            throw new IllegalArgumentException("Null userId");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public void saveUserOrcid(Long userProfileId, OrcidAuthorization orcidAuthorization)
            throws DuplicateOrcidException {
        UserOrcid userOrcid = (UserOrcid) DataAccessUtils
                .uniqueResult(hibernateTemplate.findByCriteria(DetachedCriteria.forClass(UserOrcid.class)
                        .add(Restrictions.eq("orcid", orcidAuthorization.getOrcid()))
                        .add(Restrictions.ne("ID", userProfileId))
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));

        if (userOrcid != null) {
            throw new DuplicateOrcidException(
                    "ORCiD: '" + orcidAuthorization.getOrcid() + "' is already in use by another account");
        }

        userOrcid = (UserOrcid) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserOrcid.class).add(Restrictions.eq("ID", userProfileId))
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));

        boolean isNew = (userOrcid == null);
        if (isNew) {
            userOrcid = new UserOrcid();
            userOrcid.setID(userProfileId);
        }

        //Note we don't store the token type property of the OrcidAuthorization object.
        //http://support.orcid.org/knowledgebase/articles/119985-post-oauth-token
        //The token type for our purposes will always be "bearer"

        userOrcid.setOrcid(orcidAuthorization.getOrcid());
        userOrcid.setAccessToken(orcidAuthorization.getAccessToken());
        userOrcid.setRefreshToken(orcidAuthorization.getRefreshToken());
        userOrcid.setTokenScope(orcidAuthorization.getScope());

        Calendar newExpiresIn = Calendar.getInstance();
        //expires-in is "seconds from now"
        newExpiresIn.setTimeInMillis(newExpiresIn.getTimeInMillis() + (orcidAuthorization.getExpiresIn() * 1000));
        userOrcid.setTokenExpires(newExpiresIn);

        if (isNew) {
            hibernateTemplate.save(userOrcid);
        } else {
            hibernateTemplate.update(userOrcid);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public void removeUserOrcid(Long userProfileId) {
        UserOrcid userOrcid = (UserOrcid) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserOrcid.class).add(Restrictions.eq("ID", userProfileId))
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));

        if (userOrcid != null) {
            hibernateTemplate.delete(userOrcid);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public UserOrcid getUserOrcid(Long userProfileId) {
        UserOrcid userOrcid = (UserOrcid) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserOrcid.class).add(Restrictions.eq("ID", userProfileId))
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));

        return userOrcid;
    }

    @Override
    public UserProfile getProfileForDisplay(UserProfile userProfile, boolean showPrivateFields) {
        UserProfile display = new UserProfile();
        copyFields(userProfile, display);
        if (!showPrivateFields) {
            log.debug("Removing private fields for display on user: {}", userProfile.getDisplayName());
            display.setOrganizationName(null);
            display.setOrganizationType(null);
            display.setPostalAddress(null);
            display.setPositionType(null);
        }

        //escape html in all string fields
        BeanWrapper wrapper = new BeanWrapperImpl(display);
        for (PropertyDescriptor property : wrapper.getPropertyDescriptors()) {
            if (String.class.isAssignableFrom(property.getPropertyType())) {
                String name = property.getName();
                wrapper.setPropertyValue(name, TextUtils.escapeHtml((String) wrapper.getPropertyValue(name)));
            }
        }

        return display;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<UserAlert> getAvailableAlerts() {
        List<UserAlert> alerts = new ArrayList<UserAlert>();

        final SortedMap<Integer, Pair> categoryNames = new ConcurrentSkipListMap<Integer, Pair>();

        HierarchicalConfiguration hc = (HierarchicalConfiguration) configuration;
        List<HierarchicalConfiguration> categories = hc.configurationsAt(ALERTS_CATEGORIES_CATEGORY);

        for (HierarchicalConfiguration c : categories) {
            String key = c.getString("[@key]");
            int order = c.getInt("[@displayOrder]", categoryNames.size());
            String value = c.getString("");

            categoryNames.put(order, new Pair<String, String>(key, value));
        }

        final String[] weeklyCategories = hc.getStringArray(ALERTS_WEEKLY);
        final String[] monthlyCategories = hc.getStringArray(ALERTS_MONTHLY);
        final String[] subjectFilters = hc.getStringArray(SUBJECT_FILTER);

        final Set<Map.Entry<Integer, Pair>> categoryNamesSet = categoryNames.entrySet();

        for (final Map.Entry<Integer, Pair> category : categoryNamesSet) {
            final String key = (String) category.getValue().getFirst();
            boolean weeklyCategoryKey = false;
            boolean monthlyCategoryKey = false;
            boolean subjectFilter = false;

            if (ArrayUtils.contains(weeklyCategories, key)) {
                weeklyCategoryKey = true;
            }
            if (ArrayUtils.contains(monthlyCategories, key)) {
                monthlyCategoryKey = true;
            }
            if (ArrayUtils.contains(subjectFilters, key)) {
                subjectFilter = true;
            }

            alerts.add(
                    new UserAlert((String) category.getValue().getFirst(), (String) category.getValue().getSecond(),
                            weeklyCategoryKey, monthlyCategoryKey, subjectFilter));
        }
        return alerts;
    }

    /**
     * Copy fields for updating or display. Does <b>not</b> copy some fields:
     * <ul>
     * <li>ID: never overwrite IDs on hibernate objects</li>
     * <li>userAccountUri: these don't come down from display layer, so we don't want to overwrite with null</li>
     * <li>userProfileUri: these don't come down from display layer, so we don't want to overwrite with null</li>
     * <li>roles: don't want to overwrite a user's roles when updating their profile</li>
     * </ul>
     *
     * @param source
     * @param destination
     */
    private void copyFields(UserProfile source, UserProfile destination) {
        destination.setAuthId(source.getAuthId());
        destination.setRealName(source.getRealName());
        destination.setGivenNames(source.getGivenNames());
        destination.setSurname(source.getSurname());
        destination.setTitle(source.getTitle());
        destination.setGender(source.getGender());
        destination.setEmail(source.getEmail());
        destination.setHomePage(source.getHomePage());
        destination.setWeblog(source.getWeblog());
        destination.setPublications(source.getPublications());
        destination.setDisplayName(source.getDisplayName());
        destination.setSuffix(source.getSuffix());
        destination.setPositionType(source.getPositionType());
        destination.setOrganizationName(source.getOrganizationName());
        destination.setOrganizationType(source.getOrganizationType());
        destination.setPostalAddress(source.getPostalAddress());
        destination.setCity(source.getCity());
        destination.setCountry(source.getCountry());
        destination.setBiography(source.getBiography());
        destination.setInterests(source.getInterests());
        destination.setResearchAreas(source.getResearchAreas());
        destination.setOrganizationVisibility(source.getOrganizationVisibility());
        destination.setAlertsJournals(source.getAlertsJournals());
    }

    @Override
    @Transactional
    public Long recordArticleView(Long userId, Long articleId, ArticleView.Type type) {
        if (this.advancedLogging) {
            return (Long) hibernateTemplate.save(new ArticleView(userId, articleId, type));
        } else {
            return 0L;
        }
    }

    @Override
    @Transactional
    public Long recordUserSearch(Long userProfileID, String searchTerms, String searchParams) {
        if (this.advancedLogging) {
            return (Long) hibernateTemplate.save(new UserSearch(userProfileID, searchTerms, searchParams));
        } else {
            return 0L;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<String> getJournalAlertSubjects(Long userId, String journal) {
        List<SavedSearchView> savedSearchViews = getSavedSearches(userId);

        List<String> subjects = new ArrayList<String>();

        //If the user has a journal alert for this journal, return true
        for (SavedSearchView view : savedSearchViews) {
            if (view.getSearchType() == SavedSearchType.JOURNAL_ALERT) {
                if (view.getSearchParameters().getFilterJournals().length != 1) {
                    continue;
                }

                if (view.getSearchParameters().getFilterJournals()[0].equals(journal)) {
                    String[] storedCategories = view.getSearchParameters().getFilterSubjectsDisjunction();
                    subjects.addAll(Arrays.asList(storedCategories));
                }
            }
        }

        return subjects;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Pair<Boolean, Integer> getJournalAlertAndSubjectCount(Long userId, String journal, String category) {
        List<SavedSearchView> savedSearchViews = getSavedSearches(userId);

        boolean found = false;
        int subjectCount = 0;

        //If the user has a journal alert for this journal, return true
        for (SavedSearchView view : savedSearchViews) {
            if (view.getSearchType() == SavedSearchType.JOURNAL_ALERT) {
                if (view.getSearchParameters().getFilterJournals().length != 1) {
                    continue;
                }

                if (view.getSearchParameters().getFilterJournals()[0].equals(journal)) {
                    String[] storedCategories = view.getSearchParameters().getFilterSubjectsDisjunction();
                    subjectCount += storedCategories.length;

                    for (String storedCategory : storedCategories) {
                        if (storedCategory.equals(category)) {
                            found = true;
                        }
                    }
                }
            }
        }
        return new Pair<Boolean, Integer>(found, subjectCount);
    }

    /**
     * Getter for property 'permissionsService'.
     *
     * @return Value for property 'permissionsService'.
     */
    public PermissionsService getPermissionsService() {
        return permissionsService;
    }

    /**
     * Setter for property 'permissionsService'.
     *
     * @param permissionsService Value to set for property 'permissionsService'.
     */
    @Required
    public void setPermissionsService(final PermissionsService permissionsService) {
        this.permissionsService = permissionsService;
    }

    @Required
    public void setConfiguration(Configuration configuration) {
        this.configuration = configuration;

        Object val = configuration.getProperty(ConfigurationStore.ADVANCED_USAGE_LOGGING);
        if (val != null && val.equals("true")) {
            advancedLogging = true;
        }
    }
}