/* * * Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under * one or more contributor license agreements (see COPYRIGHT for details). * The CA licenses this file to you under the GNU Affero General Public * License version 3, (the "License"); you may not use this file except in * compliance with the License. This file is part of kune. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package cc.kune.wave.server.kspecific; import java.util.HashSet; import javax.persistence.NoResultException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.waveprotocol.box.common.DeltaSequence; import org.waveprotocol.box.server.waveserver.WaveBus; import org.waveprotocol.box.server.waveserver.WaveBus.Subscriber; import org.waveprotocol.wave.model.id.IdUtil; import org.waveprotocol.wave.model.id.WaveId; import org.waveprotocol.wave.model.id.WaveletId; import org.waveprotocol.wave.model.id.WaveletName; import org.waveprotocol.wave.model.operation.wave.AddParticipant; import org.waveprotocol.wave.model.operation.wave.RemoveParticipant; import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta; import org.waveprotocol.wave.model.operation.wave.WaveletBlipOperation; import org.waveprotocol.wave.model.operation.wave.WaveletOperation; import org.waveprotocol.wave.model.version.HashedVersion; import org.waveprotocol.wave.model.wave.ParticipantId; import org.waveprotocol.wave.model.wave.data.ReadableWaveletData; import org.waveprotocol.wave.model.waveref.WaveRef; import cc.kune.common.shared.utils.TextUtils; import cc.kune.core.client.state.SiteTokens; import cc.kune.core.server.notifier.LocalUserDestinationProvider; import cc.kune.core.server.notifier.NotificationType; import cc.kune.core.server.notifier.PendingNotification; import cc.kune.core.server.notifier.PendingNotificationProvider; import cc.kune.core.server.notifier.PendingNotificationSender; import cc.kune.core.server.notifier.WaveDestinationProvider; import cc.kune.core.server.properties.KuneBasicProperties; import cc.kune.core.server.rack.ContainerListener; import cc.kune.core.server.utils.FormattedString; import cc.kune.domain.User; import cc.kune.domain.finders.UserFinder; import com.google.inject.Inject; import com.google.inject.Singleton; // TODO: Auto-generated Javadoc /** * The Class WaveEmailNotifier. * * @author vjrj@ourproject.org (Vicente J. Ruiz Jurado) */ @Singleton public class WaveEmailNotifier implements ContainerListener { /** The Constant LOG. */ public static final Log LOG = LogFactory.getLog(WaveEmailNotifier.class); /** The basic properties. */ private final KuneBasicProperties basicProperties; /** The notificator. */ private final PendingNotificationSender notificator; /** The part utils. */ private final ParticipantUtils partUtils; /** The updated waves in last hour. */ private final HashSet<WaveId> updatedWavesInLastHour; /** The user finder. */ private final UserFinder userFinder; /** The wave bus. */ private final WaveBus waveBus; /** The wave service. */ private final KuneWaveService waveService; /** * Instantiates a new wave email notifier. * * @param waveBus the wave bus * @param notificator the notificator * @param basicProperties the basic properties * @param partUtils the part utils * @param waveService the wave service * @param userFinder the user finder */ @Inject public WaveEmailNotifier(final WaveBus waveBus, final PendingNotificationSender notificator, final KuneBasicProperties basicProperties, final ParticipantUtils partUtils, final KuneWaveService waveService, final UserFinder userFinder) { this.waveBus = waveBus; this.notificator = notificator; this.basicProperties = basicProperties; this.partUtils = partUtils; this.waveService = waveService; this.userFinder = userFinder; updatedWavesInLastHour = new HashSet<WaveId>(); LOG.info("WaveEmailNotifier created"); } /** * Clear updated waves. */ public void clearUpdatedWaves() { updatedWavesInLastHour.clear(); } /* (non-Javadoc) * @see cc.kune.core.server.rack.ContainerListener#start() */ @Override public void start() { final String siteCommonName = basicProperties.getSiteCommonName(); final String siteUrl = basicProperties.getSiteUrl(); waveBus.subscribe(new Subscriber() { private PendingNotification createPendingNotif(final ParticipantId participant, final FormattedString subject, final FormattedString body) { final String address = participant.getAddress(); if (partUtils.isLocal(address)) { final String userName = partUtils.getAddressName(address); try { final User user = userFinder.findByShortName(userName); return new PendingNotification(NotificationType.email, subject, body, true, false, new LocalUserDestinationProvider(user)); } catch (final NoResultException e) { // Seems is not a local user } } return PendingNotification.NONE; } private String getTitle(final ReadableWaveletData wavelet, final ParticipantId by) { final String title = waveService.getTitle( WaveRef.of(wavelet.getWaveId(), wavelet.getWaveletId()), by.toString()); return TextUtils.notEmpty(title) ? title : "Not subject"; } private String getUrl(final ReadableWaveletData wavelet, final WaveletId waveletId) { return KuneWaveServerUtils.getUrl(WaveRef.of(wavelet.getWaveId(), waveletId)); } private FormattedString newWaveTemplate(final String by, final String url) { return FormattedString.build( "Hi there,<br><br>You have a new message by '%s' in your inbox at %s. <a href=\"%s#%s\">Read more</a>.<br>", by, siteCommonName, siteUrl, url); } private FormattedString removeWaveTemplate(final String by, final String title) { return FormattedString.build( "Hi there,<br><br>You have been removed by '%s' from message '%s' at %s. <a href=\"%s#%s\">Read more</a>.<br>", by, title, siteCommonName, siteUrl, SiteTokens.WAVE_INBOX); } private FormattedString updatedWaveTemplate(final String by, final String title, final String url) { return FormattedString.build( "Hi there,<br><br>The message '%s' was updated by '%s' in your inbox at %s. <a href=\"%s#%s\">Read more</a>.<br>", title, by, siteCommonName, siteUrl, url); } @Override public void waveletCommitted(final WaveletName waveletName, final HashedVersion version) { } @Override public void waveletUpdate(final ReadableWaveletData wavelet, final DeltaSequence deltas) { final WaveletId waveletId = wavelet.getWaveletId(); if (IdUtil.isUserDataWavelet(waveletId)) { return; } for (final TransformedWaveletDelta delta : deltas) { for (final WaveletOperation op : delta) { if (op instanceof AddParticipant) { final AddParticipant addParticipantOp = (AddParticipant) op; final ParticipantId by = addParticipantOp.getContext().getCreator(); final ParticipantId to = addParticipantOp.getParticipantId(); if (!by.equals(to)) { notificator.add(new PendingNotificationProvider() { @Override public PendingNotification get() { LOG.debug(String.format("New wave from '%s' to '%s'", by, to)); final String byS = by.toString(); return createPendingNotif(to, FormattedString.build("New message by %s", byS), newWaveTemplate(by.toString(), getUrl(wavelet, waveletId))); } }); } } else if (op instanceof RemoveParticipant) { final RemoveParticipant removeParticipantOp = (RemoveParticipant) op; final ParticipantId by = removeParticipantOp.getContext().getCreator(); final ParticipantId to = removeParticipantOp.getParticipantId(); if (!by.equals(to)) { notificator.add(new PendingNotificationProvider() { @Override public PendingNotification get() { final String title = getTitle(wavelet, by); LOG.debug(String.format("'%s' removed from wave '%s' to '%s'", by, title, to)); return createPendingNotif(to, FormattedString.build( "You have been removed as participant of message: %s", title), removeWaveTemplate(by.toString(), title)); } }); } } else if (op instanceof WaveletBlipOperation) { // Replies, etc final WaveId waveId = wavelet.getWaveId(); if (!updatedWavesInLastHour.contains(waveId)) { updatedWavesInLastHour.add(waveId); notificator.add(new PendingNotificationProvider() { @Override public PendingNotification get() { final WaveRef waveref = WaveRef.of(waveId, waveletId); final WaveletBlipOperation blipOp = (WaveletBlipOperation) op; final ParticipantId by = blipOp.getContext().getCreator(); final String title = getTitle(wavelet, by); final String url = KuneWaveServerUtils.getUrl(waveref); LOG.debug(String.format("'%s' update wave '%s'", by, title)); final String byS = by.toString(); return new PendingNotification(NotificationType.email, FormattedString.build( "%s (message updated by %s)", title, byS), updatedWaveTemplate(byS, title, url), true, false, new WaveDestinationProvider(waveref, byS)); } }); } } } } } }); LOG.info("WaveEmailNotifier started"); } /* (non-Javadoc) * @see cc.kune.core.server.rack.ContainerListener#stop() */ @Override public void stop() { } }