/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Cyclos 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 Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package nl.strohalm.cyclos.controls.members.preferences;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import nl.strohalm.cyclos.annotations.Inject;
import nl.strohalm.cyclos.controls.ActionContext;
import nl.strohalm.cyclos.controls.BaseFormAction;
import nl.strohalm.cyclos.entities.access.Channel;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
import nl.strohalm.cyclos.entities.groups.MemberGroup;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.messages.Message;
import nl.strohalm.cyclos.entities.members.messages.Message.Type;
import nl.strohalm.cyclos.entities.members.preferences.NotificationPreference;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import nl.strohalm.cyclos.entities.sms.MemberSmsStatus;
import nl.strohalm.cyclos.services.access.ChannelService;
import nl.strohalm.cyclos.services.elements.MemberService;
import nl.strohalm.cyclos.services.preferences.PreferenceService;
import nl.strohalm.cyclos.services.sms.ISmsContext;
import nl.strohalm.cyclos.utils.ActionHelper;
import nl.strohalm.cyclos.utils.RelationshipHelper;
import nl.strohalm.cyclos.utils.conversion.CoercionHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionForward;
/**
* The action for handle the notification preferences.
* @author Jefferson Magno
* @author jeancarlo
*/
public class NotificationPreferenceAction extends BaseFormAction {
private PreferenceService preferenceService;
private ChannelService channelService;
private MemberService memberService;
@Inject
public void setChannelService(final ChannelService channelService) {
this.channelService = channelService;
}
@Inject
public void setMemberService(final MemberService memberService) {
this.memberService = memberService;
}
@Inject
public void setPreferenceService(final PreferenceService preferenceService) {
this.preferenceService = preferenceService;
}
@Override
protected ActionForward handleSubmit(final ActionContext context) throws Exception {
final NotificationPreferenceForm form = context.getForm();
long memberId = form.getMemberId();
if (memberId < 1) {
memberId = context.getElement().getId();
}
// Load member and member group
final Member member = elementService.load(memberId, RelationshipHelper.nested(Element.Relationships.GROUP, MemberGroup.Relationships.SMS_MESSAGES), Member.Relationships.CHANNELS);
// Load member notification preferences
Collection<NotificationPreference> list = preferenceService.load(member);
if (list == null) {
list = new ArrayList<NotificationPreference>();
}
// Store notification preferences by type
final Map<Message.Type, NotificationPreference> map = new HashMap<Message.Type, NotificationPreference>();
for (final NotificationPreference preference : list) {
map.put(preference.getType(), preference);
}
// Check if the member have e-mail
final boolean hasEmail = StringUtils.isNotEmpty(member.getEmail());
final LocalSettings localSettings = settingsService.getLocalSettings();
final boolean smsEnabled = localSettings.isSmsEnabled();
boolean hasNotificationsBySms = false;
// Save the notification preferences
final List<Message.Type> usedTypes = preferenceService.listNotificationTypes(member);
for (final Message.Type type : Message.Type.values()) {
final String isEmailStr = (String) form.getNotificationPreference(type.name() + "_email");
final String isMessageStr = (String) form.getNotificationPreference(type.name() + "_message");
final String isSmsStr = (String) form.getNotificationPreference(type.name() + "_sms");
boolean isEmail = false;
boolean isMessage = false;
boolean isSms = false;
// If not use type, use both as false
if (usedTypes.contains(type)) {
isEmail = hasEmail ? CoercionHelper.coerce(Boolean.TYPE, isEmailStr) : false;
isMessage = CoercionHelper.coerce(Boolean.TYPE, isMessageStr);
if (type == Message.Type.FROM_ADMIN_TO_MEMBER || type == Message.Type.FROM_ADMIN_TO_GROUP) {
isMessage = true;
}
if (smsEnabled) {
isSms = CoercionHelper.coerce(Boolean.TYPE, isSmsStr);
}
}
hasNotificationsBySms |= isSms;
NotificationPreference preference = map.get(type);
if (preference == null && (isEmail || isMessage || isSms)) {
// Insert new notification preference
preference = new NotificationPreference();
preference.setType(type);
preference.setEmail(isEmail);
preference.setMessage(isMessage);
preference.setSms(isSms);
map.put(type, preference);
} else if (preference != null) {
// Update an existing notification preference
preference.setEmail(isEmail);
preference.setMessage(isMessage);
preference.setSms(isSms);
}
}
preferenceService.save(member, map.values());
if (smsEnabled) {
// Store the sms operations channel
final Channel smsChannel = channelService.getSmsChannel();
if (accessService.canChangeChannelsAccess(member) && smsChannel != null) {
final Set<Channel> channels = new HashSet<Channel>(accessService.getChannelsEnabledForMember(member));
if (form.isEnableSmsOperations()) {
channels.add(smsChannel);
} else {
channels.remove(smsChannel);
}
accessService.changeChannelsAccess(member, channels, false);
}
// The other flags come from the member sms status
preferenceService.saveSmsStatusPreferences(member, form.isAcceptFreeMailing(), form.isAcceptPaidMailing(), form.isAllowChargingSms(), hasNotificationsBySms);
}
context.sendMessage("notificationPreferences.modified");
if (context.getElement().getId() == memberId) { // my preferences
return context.getSuccessForward();
} else {
return ActionHelper.redirectWithParam(context.getRequest(), context.getSuccessForward(), "memberId", memberId);
}
}
@Override
protected void prepareForm(final ActionContext context) throws Exception {
final HttpServletRequest request = context.getRequest();
final NotificationPreferenceForm form = context.getForm();
long memberId = form.getMemberId();
if (memberId < 1) {
memberId = context.getElement().getId();
}
// Load member and member group
final Member member = elementService.load(memberId, RelationshipHelper.nested(Element.Relationships.GROUP, MemberGroup.Relationships.SMS_MESSAGES), Member.Relationships.CHANNELS);
request.setAttribute("member", member);
final LocalSettings localSettings = settingsService.getLocalSettings();
// Check which messages types can be sent by sms (group setting)
final Collection<Type> smsMessages = member.getMemberGroup().getSmsMessages();
final boolean hasSmsMessages = CollectionUtils.isNotEmpty(smsMessages);
final boolean smsEnabled = localSettings.isSmsEnabled();
request.setAttribute("smsEnabled", smsEnabled);
request.setAttribute("hasSmsMessages", hasSmsMessages);
request.setAttribute("smsEnabledTypes", smsMessages);
// Load member notification preferences
Collection<NotificationPreference> list = preferenceService.load(member);
if (list == null) {
list = new ArrayList<NotificationPreference>();
}
// Store notification preferences by type
final Map<Message.Type, NotificationPreference> map = new HashMap<Message.Type, NotificationPreference>();
for (final NotificationPreference preference : list) {
map.put(preference.getType(), preference);
}
// Check if the member have e-mail
final boolean hasEmail = StringUtils.isNotEmpty(member.getEmail()) ? true : false;
request.setAttribute("hasEmail", hasEmail);
final List<Message.Type> types = preferenceService.listNotificationTypes(member);
for (final Type type : types) {
final NotificationPreference preference = map.get(type);
final String typeMessage = type.name() + "_message";
final String typeEmail = type.name() + "_email";
final String typeSms = type.name() + "_sms";
final boolean isEmail = preference != null ? preference.isEmail() : false;
boolean isMessage = preference != null ? preference.isMessage() : false;
if (type == Message.Type.FROM_ADMIN_TO_MEMBER || type == Message.Type.FROM_ADMIN_TO_GROUP) {
isMessage = true;
}
final boolean isSms = preference != null ? preference.isSms() : false;
form.setNotificationPreference(typeMessage, isMessage);
form.setNotificationPreference(typeEmail, isEmail);
form.setNotificationPreference(typeSms, isSms);
}
request.setAttribute("types", types);
if (smsEnabled) {
final ISmsContext smsContext = memberService.getSmsContext(member);
request.setAttribute("maxFreeSms", smsContext.getFreeSms(member));
request.setAttribute("additionalChargedSms", smsContext.getAdditionalChargedSms(member));
request.setAttribute("additionalChargeAmount", smsContext.getAdditionalChargeAmount(member));
final TransferType tt = member.getMemberGroup().getMemberSettings().getSmsChargeTransferType();
request.setAttribute("additionalChargeCurrency", tt == null ? null : tt.getCurrency());
request.setAttribute("additionalChargePeriod", smsContext.getAdditionalChargedPeriod(member));
final MemberSmsStatus smsStatus = preferenceService.getMemberSmsStatus(member);
request.setAttribute("showFreeSms", smsContext.showFreeSms(smsStatus));
final Channel smsChannel = channelService.getSmsChannel();
if (smsChannel != null) {
final boolean hasAccessToSmsChannel = member.getMemberGroup().getChannels().contains(smsChannel);
form.setEnableSmsOperations(accessService.isChannelEnabledForMember(smsChannel.getInternalName(), member));
request.setAttribute("hasAccessToSmsChannel", hasAccessToSmsChannel);
if (hasAccessToSmsChannel) {
request.setAttribute("canChangeChannelAccess", accessService.canChangeChannelsAccess(member));
}
}
form.setAllowChargingSms(smsStatus.isAllowChargingSms());
form.setAcceptFreeMailing(smsStatus.isAcceptFreeMailing());
form.setAcceptPaidMailing(smsStatus.isAcceptPaidMailing());
request.setAttribute("smsStatus", smsStatus);
}
}
}