/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community 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://opensource.org/licenses/ecl2.txt * * 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.opencastproject.index.service.resources.list.provider; import static org.opencastproject.index.service.util.ListProviderUtil.splitStringList; import org.opencastproject.index.service.impl.index.AbstractSearchIndex; import org.opencastproject.index.service.impl.index.event.Event; import org.opencastproject.index.service.impl.index.event.EventIndexSchema; import org.opencastproject.index.service.impl.index.series.Series; import org.opencastproject.index.service.impl.index.series.SeriesIndexSchema; import org.opencastproject.index.service.resources.list.api.ResourceListProvider; import org.opencastproject.index.service.resources.list.api.ResourceListQuery; import org.opencastproject.index.service.util.ListProviderUtil; import org.opencastproject.security.api.Organization; import org.opencastproject.security.api.User; import org.opencastproject.security.api.UserDirectoryService; import org.opencastproject.util.data.Option; import org.apache.commons.lang3.StringUtils; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; public class ContributorsListProvider implements ResourceListProvider { private static final String PROVIDER_PREFIX = "CONTRIBUTORS"; public static final String DEFAULT = PROVIDER_PREFIX; public static final String NAMES_TO_USERNAMES = PROVIDER_PREFIX + ".NAMES.TO.USERNAMES"; public static final String USERNAMES = PROVIDER_PREFIX + ".USERNAMES"; protected static final String[] NAMES = { PROVIDER_PREFIX, USERNAMES, NAMES_TO_USERNAMES }; private static final Logger logger = LoggerFactory.getLogger(ContributorsListProvider.class); private UserDirectoryService userDirectoryService; private AbstractSearchIndex searchIndex; protected void activate(BundleContext bundleContext) { logger.info("Contributors list provider activated!"); } /** OSGi callback for users services. */ public void setUserDirectoryService(UserDirectoryService userDirectoryService) { this.userDirectoryService = userDirectoryService; } /** OSGi callback for the search index. */ public void setIndex(AbstractSearchIndex index) { this.searchIndex = index; } @Override public String[] getListNames() { return NAMES; } @Override public Map<String, String> getList(String listName, ResourceListQuery query, Organization organization) { if (listName.equalsIgnoreCase(USERNAMES)) { return getListWithUserNames(query); } else if (listName.equalsIgnoreCase(NAMES_TO_USERNAMES)) { return getListWithTechnicalPresenters(query); } else { return getList(query); } } /** * Get all of the contributors with friendly printable names. * * @param query * The query for the list including limit and offset. * @return The {@link Map} including all of the contributors. */ protected Map<String, String> getList(ResourceListQuery query) { Map<String, String> usersList = new HashMap<String, String>(); int offset = 0; int limit = 0; SortedSet<String> contributorsList = new TreeSet<String>(new Comparator<String>() { @Override public int compare(String name1, String name2) { return name1.compareTo(name2); } }); Iterator<User> users = userDirectoryService.findUsers("%", offset, limit); while (users.hasNext()) { User u = users.next(); if (StringUtils.isNotBlank(u.getName())) contributorsList.add(u.getName()); } contributorsList.addAll(splitStringList(searchIndex.getTermsForField(EventIndexSchema.CONTRIBUTOR, Option.some(new String[] { Event.DOCUMENT_TYPE })))); contributorsList.addAll(splitStringList(searchIndex.getTermsForField(EventIndexSchema.PRESENTER, Option.some(new String[] { Event.DOCUMENT_TYPE })))); contributorsList.addAll(splitStringList(searchIndex.getTermsForField(SeriesIndexSchema.CONTRIBUTORS, Option.some(new String[] { Series.DOCUMENT_TYPE })))); contributorsList.addAll(splitStringList(searchIndex.getTermsForField(SeriesIndexSchema.ORGANIZERS, Option.some(new String[] { Series.DOCUMENT_TYPE })))); contributorsList.addAll(splitStringList(searchIndex.getTermsForField(SeriesIndexSchema.PUBLISHERS, Option.some(new String[] { Series.DOCUMENT_TYPE })))); // TODO: TThis is not a good idea. // TODO: The search index can handle limit and offset. // TODO: We should not request all data. if (query != null) { if (query.getLimit().isSome()) limit = query.getLimit().get(); if (query.getOffset().isSome()) offset = query.getOffset().get(); } int i = 0; for (String contributor : contributorsList) { if (i >= offset && (limit == 0 || i < limit)) { usersList.put(contributor, contributor); } i++; } return usersList; } /** * Get the contributors list including usernames and organizations for the users available. * * @param query * The query for the list including limit and offset. * @return The {@link Map} including all of the contributors. */ protected Map<String, String> getListWithTechnicalPresenters(ResourceListQuery query) { int offset = 0; int limit = 0; List<Contributor> contributorsList = new ArrayList<Contributor>(); HashSet<String> labels = new HashSet<String>(); Iterator<User> users = userDirectoryService.findUsers("%", offset, limit); while (users.hasNext()) { User u = users.next(); if (StringUtils.isNotBlank(u.getName())) { contributorsList.add(new Contributor(u.getUsername(), u.getName())); labels.add(u.getName()); } else { contributorsList.add(new Contributor(u.getUsername(), u.getUsername())); labels.add(u.getUsername()); } } addIndexNamesToMap(labels, contributorsList, splitStringList(searchIndex .getTermsForField(EventIndexSchema.PRESENTER, Option.some(new String[] { Event.DOCUMENT_TYPE })))); addIndexNamesToMap(labels, contributorsList, splitStringList(searchIndex .getTermsForField(EventIndexSchema.CONTRIBUTOR, Option.some(new String[] { Event.DOCUMENT_TYPE })))); addIndexNamesToMap(labels, contributorsList, splitStringList(searchIndex .getTermsForField(SeriesIndexSchema.CONTRIBUTORS, Option.some(new String[] { Event.DOCUMENT_TYPE })))); addIndexNamesToMap(labels, contributorsList, splitStringList(searchIndex .getTermsForField(SeriesIndexSchema.ORGANIZERS, Option.some(new String[] { Event.DOCUMENT_TYPE })))); addIndexNamesToMap(labels, contributorsList, splitStringList(searchIndex .getTermsForField(SeriesIndexSchema.PUBLISHERS, Option.some(new String[] { Event.DOCUMENT_TYPE })))); Collections.sort(contributorsList, new Comparator<Contributor>() { @Override public int compare(Contributor contributor1, Contributor contributor2) { return contributor1.getLabel().compareTo(contributor2.getLabel()); } }); Map<String, String> contributorMap = new LinkedHashMap<>(); for (Contributor contributor : contributorsList) { contributorMap.put(contributor.getKey(), contributor.getLabel()); } return ListProviderUtil.filterMap(contributorMap, query); } /** * Get the contributors list including usernames and organizations for the users available. * * @param query * The query for the list including limit and offset. * @return The {@link Map} including all of the contributors. */ protected Map<String, String> getListWithUserNames(ResourceListQuery query) { int offset = 0; int limit = 0; List<Contributor> contributorsList = new ArrayList<Contributor>(); HashSet<String> labels = new HashSet<String>(); Iterator<User> users = userDirectoryService.findUsers("%", offset, limit); while (users.hasNext()) { User u = users.next(); if (StringUtils.isNotBlank(u.getName())) { contributorsList.add(new Contributor(u.getUsername(), u.getName())); labels.add(u.getName()); } else { contributorsList.add(new Contributor(u.getUsername(), u.getUsername())); labels.add(u.getUsername()); } } Collections.sort(contributorsList, new Comparator<Contributor>() { @Override public int compare(Contributor contributor1, Contributor contributor2) { return contributor1.getLabel().compareTo(contributor2.getLabel()); } }); Map<String, String> contributorMap = new LinkedHashMap<>(); for (Contributor contributor : contributorsList) { contributorMap.put(contributor.getKey(), contributor.getLabel()); } return ListProviderUtil.filterMap(contributorMap, query); } /** * Add all names in the index to the map if they aren't already present as a user. * * @param userLabels * The collection of user labels, the full names of the users. * @param contributors * The collection of all contributors including the index names that will be added. * @param indexNames * The list of new names from the index. */ protected void addIndexNamesToMap(Set<String> userLabels, Collection<Contributor> contributors, List<String> indexNames) { for (String indexName : indexNames) { if (!userLabels.contains(indexName)) { contributors.add(new Contributor(indexName, indexName)); } } } private class Contributor { public String getKey() { return key; } public String getLabel() { return label; } private String key; private String label; Contributor(String key, String label) { this.key = key; this.label = label; } @Override public String toString() { return key + ":" + label; } } }