/* * Copyright (c) 2011 Lockheed Martin Corporation * * 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.eurekastreams.web.client.ui.common.notification.dialog; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eurekastreams.server.domain.EntityType; import org.eurekastreams.server.domain.InAppNotificationDTO; /** * Extracts the sources from a collection of notifications for use by the notifications dialog. */ public class SourceListBuilder { /** * Returns the source key for a given notification. * * @param item * Notification. * @return Source key. */ public static String buildSourceKey(final InAppNotificationDTO item) { return item.getSourceType() + item.getSourceUniqueId(); } /** * Filter to match only notifications from a specific source. */ static class SpecificSourceFilter implements Source.Filter { /** Type of the source. */ EntityType sourceType; /** Unique ID of the source. */ String sourceUniqueId; /** * Constructor. * * @param inSource * The source. */ public SpecificSourceFilter(final Source inSource) { sourceType = inSource.getEntityType(); sourceUniqueId = inSource.getUniqueId(); } /** * {@inheritDoc} */ public boolean shouldDisplay(final InAppNotificationDTO inItem) { return sourceType == inItem.getSourceType() && sourceUniqueId.equals(inItem.getSourceUniqueId()); } } /** For sorting source filters. */ private static final Comparator<Source> SOURCE_SORTER = new Comparator<Source>() { public int compare(final Source inO1, final Source inO2) { return inO1.getDisplayName().compareTo(inO2.getDisplayName()); } }; /** Source representing all notifications. */ private final Source rootSource; /** Index of actual sources. Key is type+uniqueID. */ private final Map<String, Source> sourceIndex = new HashMap<String, Source>(); /** List of sources in display order. */ private final List<Source> sourceList; /** * Constructor - analyzes and builds lists. * * @param list * Notifications to process. * @param currentUserAccountId * Current user's account ID. */ public SourceListBuilder(final Collection<InAppNotificationDTO> list, final String currentUserAccountId) { // -- build index of sources by type with unread counts -- // create the high-level sources rootSource = new Source(null, null, "All", null, new Source.Filter() { public boolean shouldDisplay(final InAppNotificationDTO inItem) { return true; } }); Source streamSource = new Source(null, null, "Streams", rootSource, new Source.Filter() { public boolean shouldDisplay(final InAppNotificationDTO inItem) { return EntityType.PERSON == inItem.getSourceType() || EntityType.GROUP == inItem.getSourceType(); } }); Source appSource = new Source(null, null, "Apps", rootSource, new Source.Filter() { public boolean shouldDisplay(final InAppNotificationDTO inItem) { return EntityType.APPLICATION == inItem.getSourceType(); } }); // loop through all notifications, building the sources List<Source> streamSources = new ArrayList<Source>(); List<Source> appSources = new ArrayList<Source>(); int unread = 0; for (InAppNotificationDTO item : list) { String sourceKey = buildSourceKey(item); Source source = sourceIndex.get(sourceKey); if (source == null && item.getSourceType() != null) { Source parent; String name = item.getSourceName(); List<Source> midSourceList = null; switch (item.getSourceType()) { case PERSON: parent = streamSource; midSourceList = streamSources; if (currentUserAccountId.equals(item.getSourceUniqueId())) { name = ""; // sort to beginning } break; case GROUP: parent = streamSource; midSourceList = streamSources; break; case APPLICATION: parent = appSource; midSourceList = appSources; break; default: parent = null; break; } // if a parent was found, then create the source, else leave the notif for the "all" bin if (parent != null) { source = new Source(item.getSourceType(), item.getSourceUniqueId(), name, parent, null); source.setFilter(new SourceListBuilder.SpecificSourceFilter(source)); sourceIndex.put(sourceKey, source); midSourceList.add(source); } } if (!item.isRead()) { unread++; if (source != null) { source.incrementUnreadCount(); if (source.getParent() != null) { source.getParent().incrementUnreadCount(); } } } if (source != null) { source.incrementTotalCount(); if (source.getParent() != null) { source.getParent().incrementTotalCount(); } } } rootSource.setUnreadCount(unread); rootSource.setTotalCount(list.size()); // -- build list in display order -- sourceList = new ArrayList<Source>(sourceIndex.size() + 3); // "all" sourceList.add(rootSource); sourceIndex.put("@root", rootSource); // streams if (!streamSources.isEmpty()) { // all streams sourceList.add(streamSource); sourceIndex.put("@Streams", streamSource); // prepare list of stream sources: sort, set name on "My Stream" Collections.sort(streamSources, SOURCE_SORTER); if (streamSources.get(0).getDisplayName().isEmpty()) { streamSources.get(0).setDisplayName("My Stream"); } sourceList.addAll(streamSources); } // apps if (!appSources.isEmpty()) { // all apps sourceList.add(appSource); sourceIndex.put("@Apps", appSource); // prepare list of sources: sort Collections.sort(appSources, SOURCE_SORTER); sourceList.addAll(appSources); } } /** * @return the rootSource */ public Source getRootSource() { return rootSource; } /** * @return the sourceIndex */ public Map<String, Source> getSourceIndex() { return sourceIndex; } /** * @return the sourceList */ public List<Source> getSourceList() { return sourceList; } }