com.seajas.search.attender.service.task.SubscriberSenderTask.java Source code

Java tutorial

Introduction

Here is the source code for com.seajas.search.attender.service.task.SubscriberSenderTask.java

Source

/**
 * Copyright (C) 2013 Seajas, the Netherlands.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.seajas.search.attender.service.task;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.script.ScriptException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.stereotype.Component;

import com.seajas.search.attender.model.profile.Profile;
import com.seajas.search.attender.model.profile.ProfileSubscriber;
import com.seajas.search.attender.model.searchresult.SearchResult;
import com.seajas.search.attender.service.attender.AttenderService;
import com.seajas.search.attender.service.mail.MailService;
import com.seajas.search.attender.service.search.SearchService;
import com.seajas.search.attender.service.template.TemplateService;
import com.seajas.search.attender.service.template.TemplateService.TemplateResult;
import com.seajas.search.utilities.logging.SearchLogger;
import com.seajas.search.utilities.ui.InterfaceQueryUtils;

/**
 * Quartz job for notifying subscribers of new results.
 * 
 * @author Jasper van Veghel <jasper@seajas.com>
 */
@Component
public class SubscriberSenderTask {
    /**
     * The logger.
     */
    @Autowired
    protected SearchLogger logger;

    /**
     * The attender service.
     */
    @Autowired
    private AttenderService attenderService;

    /**
     * The template service.
     */
    @Autowired
    private TemplateService templateService;

    /**
     * The mail service.
     */
    @Autowired
    private MailService mailService;

    /**
     * The search service.
     */
    @Autowired
    private SearchService searchService;

    /**
     * The message source.
     */
    @Autowired
    private MessageSource messageSource;

    /**
     * The maximum thread pool size.
     */
    @Value("${attender.project.concurrent.threads.maximum}")
    private Integer threadMaximum;

    /**
     * Send out the actual profile e-mails.
     */
    public void send() {
        if (Boolean.getBoolean("attender.attending.disabled")) {
            logger.info(
                    "Attending has been explicitly disabled using 'attender.attending.disabled=true'. Skipping subscriber checks.");

            return;
        }

        logger.info("Started subscriber job");

        // Create a new UTC-based calendar to base ourselves on

        final Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
        final Date utcDate = calendar.getTime();

        // Also use a regular date for reference, to pass to the search engine

        final Date currentDate = new Date();

        // Retrieve the list of profile profiles to attend to

        List<Profile> profiles = attenderService.getNotifiableProfiles(calendar);

        if (profiles.size() == 0) {
            logger.info("No notifiable profiles found - finishing subscriber job");

            return;
        }

        // Re-initialize the mail-server, if needed

        mailService.updateWorkingMailServer();

        // Now process the profiles using a thread-pool of at most threadMaximum threads

        ExecutorService threadPool = Executors.newFixedThreadPool(Math.min(profiles.size(), threadMaximum));

        for (final Profile profile : profiles)
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    List<ProfileSubscriber> subscribers = attenderService.getNotifiableSubscribers(calendar,
                            profile.getSubscribers());

                    for (ProfileSubscriber subscriber : subscribers) {
                        try {
                            // Round up the search parameters and taxonomies into a concise parameter list

                            Map<String, String> searchParameters = InterfaceQueryUtils
                                    .combineParametersAndTaxonomies(profile.getSearchParametersMap(),
                                            profile.getTaxonomyIdentifierNumbers());

                            String searchQuery = InterfaceQueryUtils.createQueryFromParameters(profile.getQuery(),
                                    searchParameters);

                            // Determine the start date depending on the user's last notification date, and retrieve the results

                            List<SearchResult> searchResults = searchService.performSearch(profile.getQuery(),
                                    subscriber.getLastNotification(), currentDate, searchParameters,
                                    mailService.getResultsPerMessage(), subscriber.getEmailLanguage());

                            if (logger.isInfoEnabled())
                                logger.info("Found " + searchResults.size() + " result(s) for profile with ID "
                                        + profile.getId() + " and query '" + profile.getQuery() + "'");

                            // Now create a template result based on the search results

                            TemplateResult templateResult = templateService.createResults(
                                    subscriber.getEmailLanguage(), searchQuery, profile.getQuery(),
                                    subscriber.getUniqueId(), profile.getUniqueId(), searchResults);

                            // Take the subject in the given language, or resort to the default language if it doesn't exist (yet)

                            String subject = null;

                            try {
                                subject = messageSource.getMessage(
                                        "mail.results.subject."
                                                + subscriber.getNotificationType().toString().toLowerCase(),
                                        new Object[] { profile.getQuery() },
                                        new Locale(subscriber.getEmailLanguage()));
                            } catch (NoSuchMessageException e) {
                                logger.warn("Could not retrieve results message subject header in language "
                                        + subscriber.getEmailLanguage() + ", resorting to the default language "
                                        + attenderService.getDefaultApplicationLanguage());

                                subject = messageSource.getMessage("mail.confirmation.subject",
                                        new Object[] { profile.getQuery() },
                                        new Locale(attenderService.getDefaultApplicationLanguage()));
                            }

                            // And send out the actual e-mail

                            if (mailService.hasWorkingMailServer())
                                mailService.sendMessage(subscriber.getEmail(), subject,
                                        templateResult.getTextResult(), templateResult.getHtmlResult());
                            else
                                logger.error(
                                        "Could not e-mail the results message - no mail server has been configured. Users may retrieve results using the RSS feed.");

                            // Update the processed subscribers' lastNotification indicator

                            attenderService.updateProfileSubscriberLastNotification(subscriber.getId(), utcDate);
                        } catch (ScriptException e) {
                            logger.error("Could not create a template result", e);
                        }
                    }
                }
            });

        logger.info("Finishing subscriber job");
    }
}