Package org.eurekastreams.server.action.execution.notification.notifier

Source Code of org.eurekastreams.server.action.execution.notification.notifier.InAppNotificationNotifier

/*
* 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.server.action.execution.notification.notifier;

import java.io.StringWriter;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.eurekastreams.commons.exceptions.OutOfDateObjectException;
import org.eurekastreams.commons.server.UserActionRequest;
import org.eurekastreams.server.action.execution.notification.NotificationPropertyKeys;
import org.eurekastreams.server.domain.Identifiable;
import org.eurekastreams.server.domain.InAppNotificationEntity;
import org.eurekastreams.server.domain.NotificationType;
import org.eurekastreams.server.domain.Person;
import org.eurekastreams.server.domain.UnreadInAppNotificationCountDTO;
import org.eurekastreams.server.persistence.mappers.DomainMapper;
import org.eurekastreams.server.persistence.mappers.requests.PersistenceRequest;
import org.eurekastreams.server.search.modelview.PersonModelView;

/**
* Notifier for in-app notifications. Builds the messages and stores them in the database.
*/
public class InAppNotificationNotifier implements Notifier
{
    /** Apache Velocity templating engine. */
    private final VelocityEngine velocityEngine;

    /**
     * Global context for Apache Velocity templating engine. (Holds system-wide properties.)
     */
    private final Context velocityGlobalContext;

    /** Message templates by notification type. */
    private final Map<NotificationType, String> templates;

    /** Aggregate message templates by notification type. */
    private final Map<NotificationType, String> aggregateTemplates;

    /** Mapper to persist the notification. */
    private final DomainMapper<PersistenceRequest<InAppNotificationEntity>, Boolean> insertMapper;

    /** Mapper to update aggregate notifications. */
    private final DomainMapper<PersistenceRequest<InAppNotificationEntity>, Boolean> updateMapper;

    /** Mapper to sync unread alert count in cache. */
    private final DomainMapper<Long, UnreadInAppNotificationCountDTO> syncMapper;

    /** Provides a dummy person object for persisting the in-app entity. */
    private final DomainMapper<Long, Person> placeholderPersonMapper;

    /** Looks up existing notifications for aggregation. */
    private final DomainMapper<InAppNotificationEntity, InAppNotificationEntity> existingNotificationMapper;

    /**
     * Constructor.
     *
     * @param inVelocityEngine
     *            Apache Velocity templating engine.
     * @param inVelocityGlobalContext
     *            Global context for Apache Velocity templating engine.
     * @param inTemplates
     *            Message templates by notification type.
     * @param inAggregateTemplates
     *            Aggregate message templates by notification type.
     * @param inInsertMapper
     *            Mapper to persist the notification.
     * @param inUpdateMapper
     *            Mapper to update existing notifications.
     * @param inSyncMapper
     *            Mapper to sync unread alert count in cache.
     * @param inPlaceholderPersonMapper
     *            Provides a dummy person object for persisting the in-app entity.
     * @param inExistingNotificationMapper
     *            Mapper to search for existing notifications that can be aggregated with the current notification
     */
    public InAppNotificationNotifier(final VelocityEngine inVelocityEngine, final Context inVelocityGlobalContext,
            final Map<NotificationType, String> inTemplates, final Map<NotificationType, String> inAggregateTemplates,
            final DomainMapper<PersistenceRequest<InAppNotificationEntity>, Boolean> inInsertMapper,
            final DomainMapper<PersistenceRequest<InAppNotificationEntity>, Boolean> inUpdateMapper,
            final DomainMapper<Long, UnreadInAppNotificationCountDTO> inSyncMapper,
            final DomainMapper<Long, Person> inPlaceholderPersonMapper,
            final DomainMapper<InAppNotificationEntity, InAppNotificationEntity> inExistingNotificationMapper)
    {
        velocityEngine = inVelocityEngine;
        velocityGlobalContext = inVelocityGlobalContext;
        templates = inTemplates;
        aggregateTemplates = inAggregateTemplates;
        insertMapper = inInsertMapper;
        updateMapper = inUpdateMapper;
        syncMapper = inSyncMapper;
        placeholderPersonMapper = inPlaceholderPersonMapper;
        existingNotificationMapper = inExistingNotificationMapper;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<UserActionRequest> notify(final NotificationType inType, final Collection<Long> inRecipients,
            final Map<String, Object> inProperties, final Map<Long, PersonModelView> inRecipientIndex)
            throws Exception
    {
        Context velocityContext = new VelocityContext(new VelocityContext(inProperties, velocityGlobalContext));
        velocityContext.put("context", velocityContext);
        velocityContext.put("type", inType);

        for (long recipientId : inRecipients)
        {
            Person recipient = placeholderPersonMapper.execute(recipientId);
            if (recipient == null)
            {
                continue;
            }

            if (aggregateTemplates.containsKey(inType))
            {
                updateAggregateNotification(recipient, inType, inProperties, velocityContext);
            }
            else
            {
                createNewNotification(recipient, inType, inProperties, velocityContext);
            }
        }
        return null;
    }

    /**
     * Handles aggregated notification types. Checks for an existing notification of the same type to the same
     * recipient. If it finds an existing notification, it increments its count. Otherwise, it creates a new
     * notification.
     *
     * @param recipient
     *            The person to notify
     * @param inType
     *            The type of the notification
     * @param inProperties
     *            Additional info about the notification
     * @param velocityContext
     *            Velocity context used to generate notification message
     */
    private void updateAggregateNotification(final Person recipient, final NotificationType inType,
            final Map<String, Object> inProperties, final Context velocityContext)
    {
        InAppNotificationEntity searchCriteria = new InAppNotificationEntity();
        searchCriteria.setRecipient(recipient);
        searchCriteria.setNotificationType(inType);
        searchCriteria.setUrl((String) inProperties.get(NotificationPropertyKeys.URL));
        InAppNotificationEntity existingAggregateNotification = existingNotificationMapper.execute(searchCriteria);

        if (existingAggregateNotification == null)
        {
            createNewNotification(recipient, inType, inProperties, velocityContext);
            return;
        }

        int newAggregationCount = existingAggregateNotification.getAggregationCount() + 1;
        existingAggregateNotification.setAggregationCount(newAggregationCount);

        existingAggregateNotification.setNotificationDate(new Date());

        String template = aggregateTemplates.get(inType);
        if (template == null)
        {
            return;
        }

        velocityContext.put("recipient", recipient);
        velocityContext.put("aggregationCount", newAggregationCount);
        StringWriter writer = new StringWriter();
        velocityEngine.evaluate(velocityContext, writer, "InAppNotification-" + inType, template);

        String message = writer.toString();
        existingAggregateNotification.setMessage(message);

        try
        {
            updateMapper.execute(new PersistenceRequest<InAppNotificationEntity>(existingAggregateNotification));
        }
        catch (OutOfDateObjectException e)
        {
            updateAggregateNotification(recipient, inType, inProperties, velocityContext);
        }

        syncMapper.execute(recipient.getId());
    }

    /**
     * Creates a new notification.
     *
     * @param recipient
     *            The person to notify
     * @param inType
     *            The type of the notification
     * @param inProperties
     *            Additional info about the notification
     * @param velocityContext
     *            Velocity context used to generate notification message
     */
    private void createNewNotification(final Person recipient, final NotificationType inType,
            final Map<String, Object> inProperties, final Context velocityContext)
    {
        InAppNotificationEntity dbNotif = new InAppNotificationEntity();
        dbNotif.setNotificationType(inType);
        dbNotif.setRecipient(recipient);
        dbNotif.setUrl((String) inProperties.get(NotificationPropertyKeys.URL));
        dbNotif.setHighPriority(Boolean.TRUE.equals(inProperties.get(NotificationPropertyKeys.HIGH_PRIORITY)));

        Object obj = inProperties.get(NotificationPropertyKeys.SOURCE);
        if (obj instanceof Identifiable)
        {
            Identifiable source = (Identifiable) obj;
            dbNotif.setSourceType(source.getEntityType());
            dbNotif.setSourceUniqueId(source.getUniqueId());
            dbNotif.setSourceName(source.getDisplayName());
        }
        obj = inProperties.get(NotificationPropertyKeys.ACTOR);
        if (obj instanceof Identifiable)
        {
            Identifiable actor = (Identifiable) obj;
            dbNotif.setAvatarOwnerType(actor.getEntityType());
            dbNotif.setAvatarOwnerUniqueId(actor.getUniqueId());
        }

        String template = templates.get(inType);
        if (template == null)
        {
            return;
        }

        velocityContext.put("recipient", recipient);
        StringWriter writer = new StringWriter();
        velocityEngine.evaluate(velocityContext, writer, "InAppNotification-" + inType, template);

        String message = writer.toString();
        dbNotif.setMessage(message);

        insertMapper.execute(new PersistenceRequest<InAppNotificationEntity>(dbNotif));

        syncMapper.execute(recipient.getId());
    }
}
TOP

Related Classes of org.eurekastreams.server.action.execution.notification.notifier.InAppNotificationNotifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.