/*
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.groups;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import nl.strohalm.cyclos.access.MemberPermission;
import nl.strohalm.cyclos.access.Permission;
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.access.TransactionPassword;
import nl.strohalm.cyclos.entities.accounts.AccountType;
import nl.strohalm.cyclos.entities.accounts.cards.CardType;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferTypeQuery;
import nl.strohalm.cyclos.entities.customization.files.CustomizedFile;
import nl.strohalm.cyclos.entities.customization.files.CustomizedFileQuery;
import nl.strohalm.cyclos.entities.groups.AdminGroup;
import nl.strohalm.cyclos.entities.groups.BasicGroupSettings;
import nl.strohalm.cyclos.entities.groups.BasicGroupSettings.PasswordPolicy;
import nl.strohalm.cyclos.entities.groups.BrokerGroup;
import nl.strohalm.cyclos.entities.groups.Group;
import nl.strohalm.cyclos.entities.groups.Group.Nature;
import nl.strohalm.cyclos.entities.groups.GroupQuery;
import nl.strohalm.cyclos.entities.groups.MemberGroup;
import nl.strohalm.cyclos.entities.groups.MemberGroupSettings;
import nl.strohalm.cyclos.entities.groups.MemberGroupSettings.EmailValidation;
import nl.strohalm.cyclos.entities.groups.OperatorGroup;
import nl.strohalm.cyclos.entities.groups.SystemGroup;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.RegistrationAgreement;
import nl.strohalm.cyclos.entities.members.messages.Message;
import nl.strohalm.cyclos.entities.members.messages.Message.Type;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import nl.strohalm.cyclos.services.access.ChannelService;
import nl.strohalm.cyclos.services.accounts.AccountTypeService;
import nl.strohalm.cyclos.services.accounts.MemberAccountTypeQuery;
import nl.strohalm.cyclos.services.accounts.cards.CardTypeService;
import nl.strohalm.cyclos.services.customization.CustomizedFileService;
import nl.strohalm.cyclos.services.elements.RegistrationAgreementService;
import nl.strohalm.cyclos.services.transactions.TransactionContext;
import nl.strohalm.cyclos.services.transfertypes.TransferTypeService;
import nl.strohalm.cyclos.utils.ActionHelper;
import nl.strohalm.cyclos.utils.CustomizationHelper;
import nl.strohalm.cyclos.utils.RelationshipHelper;
import nl.strohalm.cyclos.utils.RequestHelper;
import nl.strohalm.cyclos.utils.TimePeriod;
import nl.strohalm.cyclos.utils.TimePeriod.Field;
import nl.strohalm.cyclos.utils.binding.BeanBinder;
import nl.strohalm.cyclos.utils.binding.DataBinder;
import nl.strohalm.cyclos.utils.binding.DataBinderHelper;
import nl.strohalm.cyclos.utils.binding.MapBinder;
import nl.strohalm.cyclos.utils.binding.PropertyBinder;
import nl.strohalm.cyclos.utils.binding.SimpleCollectionBinder;
import nl.strohalm.cyclos.utils.conversion.IdConverter;
import nl.strohalm.cyclos.utils.query.PageHelper;
import nl.strohalm.cyclos.utils.validation.ValidationException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionForward;
/**
* Action used to edit a group
* @author luis
* @author Jefferson Magno
*/
public class EditGroupAction extends BaseFormAction {
private static Group.Nature getGroupNature(final ActionContext context, final boolean acceptEmpty) {
try {
final EditGroupForm form = context.getForm();
final String nature = (String) form.getGroup("nature");
if (acceptEmpty && StringUtils.isBlank(nature)) {
return null;
} else {
return Group.Nature.valueOf(nature);
}
} catch (final Exception e) {
throw new ValidationException();
}
}
private CustomizationHelper customizationHelper;
private AccountTypeService accountTypeService;
private RegistrationAgreementService registrationAgreementService;
private CustomizedFileService customizedFileService;
private TransferTypeService transferTypeService;
private CardTypeService cardTypeService;
private ChannelService channelService;
private Map<Group.Nature, DataBinder<? extends Group>> dataBinders;
public AccountTypeService getAccountTypeService() {
return accountTypeService;
}
public CustomizedFileService getCustomizedFileService() {
return customizedFileService;
}
public DataBinder<? extends Group> getDataBinder(final Group.Nature nature) {
if (dataBinders == null) {
dataBinders = new EnumMap<Group.Nature, DataBinder<? extends Group>>(Group.Nature.class);
final BeanBinder<BasicGroupSettings> basicSettingsBinder = BeanBinder.instance(BasicGroupSettings.class, "basicSettings");
final BeanBinder<MemberGroupSettings> memberSettingsBinder = BeanBinder.instance(MemberGroupSettings.class, "memberSettings");
final BeanBinder<AdminGroup> adminGroupBinder = BeanBinder.instance(AdminGroup.class);
initBasic(adminGroupBinder, basicSettingsBinder);
initSystem(adminGroupBinder);
dataBinders.put(Group.Nature.ADMIN, adminGroupBinder);
final BeanBinder<MemberGroup> memberGroupBinder = BeanBinder.instance(MemberGroup.class);
initBasic(memberGroupBinder, basicSettingsBinder);
initSystem(memberGroupBinder);
initMember(memberGroupBinder, memberSettingsBinder);
dataBinders.put(Group.Nature.MEMBER, memberGroupBinder);
final BeanBinder<OperatorGroup> operatorGroupBinder = BeanBinder.instance(OperatorGroup.class);
initBasic(operatorGroupBinder, basicSettingsBinder);
initOperator(operatorGroupBinder);
dataBinders.put(Group.Nature.OPERATOR, operatorGroupBinder);
final BeanBinder<BrokerGroup> brokerGroupBinder = BeanBinder.instance(BrokerGroup.class);
initBasic(brokerGroupBinder, basicSettingsBinder);
initSystem(brokerGroupBinder);
initMember(brokerGroupBinder, memberSettingsBinder);
initBroker(brokerGroupBinder);
dataBinders.put(Group.Nature.BROKER, brokerGroupBinder);
}
return dataBinders.get(nature);
}
@Inject
public void setAccountTypeService(final AccountTypeService accountTypeService) {
this.accountTypeService = accountTypeService;
}
@Inject
public void setCardTypeService(final CardTypeService cardTypeService) {
this.cardTypeService = cardTypeService;
}
@Inject
public void setChannelService(final ChannelService channelService) {
this.channelService = channelService;
}
@Inject
public void setCustomizationHelper(final CustomizationHelper customizationHelper) {
this.customizationHelper = customizationHelper;
}
@Inject
public void setCustomizedFileService(final CustomizedFileService customizedFileService) {
this.customizedFileService = customizedFileService;
}
@Inject
public void setRegistrationAgreementService(final RegistrationAgreementService registrationAgreementService) {
this.registrationAgreementService = registrationAgreementService;
}
@Inject
public void setTransferTypeService(final TransferTypeService transferTypeService) {
this.transferTypeService = transferTypeService;
}
@Override
protected ActionForward handleSubmit(final ActionContext context) throws Exception {
final EditGroupForm form = context.getForm();
Group group = readGroup(context);
final Group baseGroup = readBaseGroup(context);
final boolean isInsert = group.getId() == null;
// Persist the group
if (isInsert) {
group = groupService.insert(group, baseGroup);
} else {
group = groupService.update(group, form.isForceAccept());
}
// Ensure the customized files collection is reloaded (for example, a group could be copied from other, and we need the collection to be
// up-to-date)
group = groupService.reload(group.getId(), Group.Relationships.CUSTOMIZED_FILES);
// Physically update the files
for (final CustomizedFile file : group.getCustomizedFiles()) {
final File physicalFile = customizationHelper.customizedFileOf(file);
customizationHelper.updateFile(physicalFile, file);
}
context.sendMessage(isInsert ? "group.inserted" : "group.modified");
return ActionHelper.redirectWithParam(context.getRequest(), context.getSuccessForward(), "groupId", group.getId());
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
protected void prepareForm(final ActionContext context) throws Exception {
final HttpServletRequest request = context.getRequest();
final EditGroupForm form = context.getForm();
final long id = form.getGroupId();
boolean editable = false;
boolean canManageFiles = false;
final Map<Group.Nature, Permission> permissionByNature = ListGroupsAction.getManageGroupPermissionByNatureMap();
final boolean isInsert = id <= 0L;
if (isInsert) {
// Prepare for insert
List<Group.Nature> natures = new ArrayList<Group.Nature>();
if (context.isAdmin()) {
// Put in the request the name of permission used to manage a type of group
request.setAttribute("permissionByNature", permissionByNature);
for (final Group.Nature nature : permissionByNature.keySet()) {
final Permission permission = permissionByNature.get(nature);
if (permissionService.hasPermission(permission)) {
natures.add(nature);
}
}
} else {
// It's a member inserting an operator group
final GroupQuery groupQuery = new GroupQuery();
groupQuery.setMember((Member) context.getElement());
final List<OperatorGroup> baseGroups = (List<OperatorGroup>) groupService.search(groupQuery);
request.setAttribute("baseGroups", baseGroups);
request.setAttribute("isOperatorGroup", true);
natures = Collections.singletonList(Group.Nature.OPERATOR);
}
request.setAttribute("natures", natures);
RequestHelper.storeEnum(request, Group.Status.class, "status");
editable = true;
} else {
// Prepare for modify
Group group = groupService.load(id, Group.Relationships.CUSTOMIZED_FILES, MemberGroup.Relationships.CHANNELS);
final boolean isMemberGroup = MemberGroup.class.isAssignableFrom(group.getNature().getGroupClass());
final boolean isBrokerGroup = BrokerGroup.class.isAssignableFrom(group.getNature().getGroupClass());
final boolean isOperatorGroup = OperatorGroup.class.isAssignableFrom(group.getNature().getGroupClass());
if (group.getStatus().isEnabled()) {
request.setAttribute("deactivationTimePeriodFields", Arrays.asList(Field.SECONDS, Field.MINUTES, Field.HOURS, Field.DAYS));
request.setAttribute("passwordExpiresAfterFields", Arrays.asList(Field.DAYS, Field.WEEKS, Field.MONTHS, Field.YEARS));
RequestHelper.storeEnum(request, TransactionPassword.class, "transactionPasswords");
if (isMemberGroup) {
final MemberGroup memberGroup = (MemberGroup) group;
// Check if the group has access to a channel that uses pin
final boolean usesPin = groupService.usesPin(memberGroup);
request.setAttribute("usesPin", usesPin);
// Retrieve the registration agreements
final List<RegistrationAgreement> registrationAgreements = registrationAgreementService.listAll();
request.setAttribute("registrationAgreements", registrationAgreements);
// Retrieve the associated accounts
request.setAttribute("timePeriodFields", Arrays.asList(Field.DAYS, Field.WEEKS, Field.MONTHS, Field.YEARS));
final MemberAccountTypeQuery atQuery = new MemberAccountTypeQuery();
atQuery.setRelatedToGroup(memberGroup);
request.setAttribute("accountTypes", accountTypeService.search(atQuery));
// Sort the message types using their messages
final List<Type> messageTypes = Arrays.asList(Message.Type.values());
final Comparator cmp = new Comparator() {
@Override
public int compare(final Object o1, final Object o2) {
final String msg1 = context.message("message.type." + o1);
final String msg2 = context.message("message.type." + o2);
return msg1.compareTo(msg2);
}
};
Collections.sort(messageTypes, cmp);
request.setAttribute("messageTypes", messageTypes);
// we create a wrapper ArrayList because the list must implement the remove method
final List<Type> smsMessageTypes = new ArrayList<Type>(Arrays.asList(Message.Type.values()));
CollectionUtils.filter(smsMessageTypes, new Predicate() {
@Override
public boolean evaluate(final Object object) {
final Message.Type type = (Message.Type) object;
switch (type) {
case FROM_MEMBER:
case FROM_ADMIN_TO_MEMBER:
case FROM_ADMIN_TO_GROUP:
return false;
default:
return true;
}
}
});
Collections.sort(smsMessageTypes, cmp);
request.setAttribute("smsMessageTypes", smsMessageTypes);
// Store the possible groups for expiration
final GroupQuery query = new GroupQuery();
query.setNatures(Group.Nature.MEMBER, Group.Nature.BROKER);
final List<? extends Group> groups = groupService.search(query);
groups.remove(group);
request.setAttribute("possibleExpirationGroups", groups);
request.setAttribute("expirationTimeFields", Arrays.asList(TimePeriod.Field.DAYS, TimePeriod.Field.WEEKS, TimePeriod.Field.MONTHS, TimePeriod.Field.YEARS));
// Store transfer types for SMS charge
final TransferTypeQuery ttQuery = new TransferTypeQuery();
ttQuery.setFromGroups(Collections.singletonList(memberGroup));
ttQuery.setToNature(AccountType.Nature.SYSTEM);
final List<TransferType> smsChargeTransferTypes = transferTypeService.search(ttQuery);
request.setAttribute("smsChargeTransferTypes", smsChargeTransferTypes);
request.setAttribute("smsAdditionalChargedPeriodFields", Arrays.asList(Field.DAYS, Field.WEEKS, Field.MONTHS));
// Retrieve the card types
request.setAttribute("cardTypes", cardTypeService.listAll());
}
if (isBrokerGroup) {
// Retrieve the possible groups for registered members by broker
final GroupQuery query = new GroupQuery();
query.setNatures(Group.Nature.MEMBER, Group.Nature.BROKER);
query.setStatus(Group.Status.NORMAL);
request.setAttribute("memberGroups", groupService.search(query));
}
if (isMemberGroup || isBrokerGroup) {
RequestHelper.storeEnum(request, MemberGroupSettings.ExternalAdPublication.class, "externalAdPublications");
}
if (isOperatorGroup) {
// Load the associated transaction types for the max amount per day
group = groupService.load(group.getId(), RelationshipHelper.nested(OperatorGroup.Relationships.MEMBER, Element.Relationships.GROUP), OperatorGroup.Relationships.MAX_AMOUNT_PER_DAY_BY_TRANSFER_TYPE, OperatorGroup.Relationships.MAX_AMOUNT_PER_DAY_BY_TRANSFER_TYPE);
final OperatorGroup operatorGroup = (OperatorGroup) group;
request.setAttribute("transferTypes", operatorGroup.getMember().getGroup().getTransferTypes());
}
// Retrieve the associated customized files
final CustomizedFileQuery cfQuery = new CustomizedFileQuery();
cfQuery.setGroup(group);
request.setAttribute("customizedFiles", customizedFileService.search(cfQuery));
// Check whether the login page name will be shown
request.setAttribute("showLoginPageName", customizationHelper.isAnyFileRelatedToLoginPage(group.getCustomizedFiles()));
}
getDataBinder(group.getNature()).writeAsString(form.getGroup(), group);
request.setAttribute("group", group);
request.setAttribute("isMemberGroup", isMemberGroup);
request.setAttribute("isBrokerGroup", isBrokerGroup);
request.setAttribute("isOperatorGroup", isOperatorGroup);
if (isMemberGroup) {
// Show scheduling options when there's a schedulable transfer type
final TransferTypeQuery ttQuery = new TransferTypeQuery();
ttQuery.setPageForCount();
ttQuery.setContext(TransactionContext.PAYMENT);
ttQuery.setGroup(group);
ttQuery.setSchedulable(true);
request.setAttribute("showScheduling", PageHelper.getTotalCount(transferTypeService.search(ttQuery)) > 0);
// Channels that the group of member have access
final Collection<Channel> channels = channelService.list();
// The "web" channel can not be customized by the user, so it should not be sent to the JSP page
final Channel webChannel = channelService.loadByInternalName(Channel.WEB);
channels.remove(webChannel);
request.setAttribute("channels", channels);
RequestHelper.storeEnum(request, EmailValidation.class, "emailValidations");
}
if (context.isAdmin()) {
AdminGroup adminGroup = context.getGroup();
adminGroup = groupService.load(adminGroup.getId(), AdminGroup.Relationships.MANAGES_GROUPS);
if (permissionService.hasPermission(permissionByNature.get(group.getNature())) && (Group.Nature.ADMIN.equals(group.getNature()) || adminGroup.getManagesGroups().contains(group))) {
editable = true;
}
} else {
// It's a member updating an operator group
editable = permissionService.hasPermission(MemberPermission.OPERATORS_MANAGE);
}
canManageFiles = customizedFileService.canViewOrManageInGroup(group);
}
request.setAttribute("isInsert", isInsert);
request.setAttribute("editable", editable);
request.setAttribute("canManageFiles", canManageFiles);
RequestHelper.storeEnum(request, PasswordPolicy.class, "passwordPolicies");
}
@Override
protected void validateForm(final ActionContext context) {
final Group group = readGroup(context);
// Check if it's a insert operation
groupService.validate(group);
if (group instanceof MemberGroup) {
final EditGroupForm form = context.getForm();
final MemberGroup memberGroup = (MemberGroup) group;
// Ensure the smsContext is present when the checkbox for using a custom context is checked
if (form.isUseCustomSMSContextClass() && StringUtils.isEmpty(memberGroup.getMemberSettings().getSmsContextClassName())) {
throw new ValidationException("errors.required", context.message("group.settings.smsContextClassName"));
}
}
}
private void initBasic(final BeanBinder<? extends Group> groupBinder, final BeanBinder<? extends BasicGroupSettings> basicSettingsBinder) {
groupBinder.registerBinder("basicSettings", basicSettingsBinder);
groupBinder.registerBinder("id", PropertyBinder.instance(Long.class, "id", IdConverter.instance()));
groupBinder.registerBinder("name", PropertyBinder.instance(String.class, "name"));
groupBinder.registerBinder("description", PropertyBinder.instance(String.class, "description"));
groupBinder.registerBinder("status", PropertyBinder.instance(Group.Status.class, "status"));
basicSettingsBinder.registerBinder("passwordLength", DataBinderHelper.rangeConstraintBinder("passwordLength"));
basicSettingsBinder.registerBinder("passwordPolicy", PropertyBinder.instance(PasswordPolicy.class, "passwordPolicy"));
basicSettingsBinder.registerBinder("maxPasswordWrongTries", PropertyBinder.instance(Integer.TYPE, "maxPasswordWrongTries"));
basicSettingsBinder.registerBinder("deactivationAfterMaxPasswordTries", DataBinderHelper.timePeriodBinder("deactivationAfterMaxPasswordTries"));
basicSettingsBinder.registerBinder("passwordExpiresAfter", DataBinderHelper.timePeriodBinder("passwordExpiresAfter"));
basicSettingsBinder.registerBinder("transactionPassword", PropertyBinder.instance(TransactionPassword.class, "transactionPassword"));
basicSettingsBinder.registerBinder("transactionPasswordLength", PropertyBinder.instance(Integer.TYPE, "transactionPasswordLength"));
basicSettingsBinder.registerBinder("maxTransactionPasswordWrongTries", PropertyBinder.instance(Integer.TYPE, "maxTransactionPasswordWrongTries"));
basicSettingsBinder.registerBinder("hideCurrencyOnPayments", PropertyBinder.instance(Boolean.TYPE, "hideCurrencyOnPayments"));
}
private void initBroker(final BeanBinder<? extends BrokerGroup> brokerGroupBinder) {
brokerGroupBinder.registerBinder("possibleInitialGroups", SimpleCollectionBinder.instance(MemberGroup.class, "possibleInitialGroups"));
}
private void initMember(final BeanBinder<? extends MemberGroup> memberGroupBinder, final BeanBinder<? extends MemberGroupSettings> memberSettingsBinder) {
memberGroupBinder.registerBinder("memberSettings", memberSettingsBinder);
memberGroupBinder.registerBinder("active", PropertyBinder.instance(Boolean.TYPE, "active"));
memberGroupBinder.registerBinder("initialGroup", PropertyBinder.instance(Boolean.TYPE, "initialGroup"));
memberGroupBinder.registerBinder("initialGroupShow", PropertyBinder.instance(String.class, "initialGroupShow"));
memberGroupBinder.registerBinder("registrationAgreement", PropertyBinder.instance(RegistrationAgreement.class, "registrationAgreement"));
memberGroupBinder.registerBinder("defaultMailMessages", SimpleCollectionBinder.instance(Message.Type.class, "defaultMailMessages"));
memberGroupBinder.registerBinder("smsMessages", SimpleCollectionBinder.instance(Message.Type.class, "smsMessages"));
memberGroupBinder.registerBinder("defaultSmsMessages", SimpleCollectionBinder.instance(Message.Type.class, "defaultSmsMessages"));
memberGroupBinder.registerBinder("defaultAllowChargingSms", PropertyBinder.instance(Boolean.TYPE, "defaultAllowChargingSms"));
memberGroupBinder.registerBinder("defaultAcceptFreeMailing", PropertyBinder.instance(Boolean.TYPE, "defaultAcceptFreeMailing"));
memberGroupBinder.registerBinder("defaultAcceptPaidMailing", PropertyBinder.instance(Boolean.TYPE, "defaultAcceptPaidMailing"));
memberGroupBinder.registerBinder("channels", SimpleCollectionBinder.instance(Channel.class, "channels"));
memberGroupBinder.registerBinder("defaultChannels", SimpleCollectionBinder.instance(Channel.class, "defaultChannels"));
memberGroupBinder.registerBinder("cardType", PropertyBinder.instance(CardType.class, "cardType"));
final LocalSettings localSettings = settingsService.getLocalSettings();
memberSettingsBinder.registerBinder("pinLength", DataBinderHelper.rangeConstraintBinder("pinLength"));
memberSettingsBinder.registerBinder("maxPinWrongTries", PropertyBinder.instance(Integer.TYPE, "maxPinWrongTries"));
memberSettingsBinder.registerBinder("pinBlockTimeAfterMaxTries", DataBinderHelper.timePeriodBinder("pinBlockTimeAfterMaxTries"));
memberSettingsBinder.registerBinder("pinLength", DataBinderHelper.rangeConstraintBinder("pinLength"));
memberSettingsBinder.registerBinder("smsChargeTransferType", PropertyBinder.instance(TransferType.class, "smsChargeTransferType"));
memberSettingsBinder.registerBinder("smsChargeAmount", PropertyBinder.instance(BigDecimal.class, "smsChargeAmount", localSettings.getNumberConverter()));
memberSettingsBinder.registerBinder("smsFree", PropertyBinder.instance(Integer.TYPE, "smsFree"));
memberSettingsBinder.registerBinder("smsShowFreeThreshold", PropertyBinder.instance(Integer.TYPE, "smsShowFreeThreshold"));
memberSettingsBinder.registerBinder("smsAdditionalCharged", PropertyBinder.instance(Integer.TYPE, "smsAdditionalCharged"));
memberSettingsBinder.registerBinder("smsAdditionalChargedPeriod", DataBinderHelper.timePeriodBinder("smsAdditionalChargedPeriod"));
memberSettingsBinder.registerBinder("smsContextClassName", PropertyBinder.instance(String.class, "smsContextClassName"));
memberSettingsBinder.registerBinder("maxAdsPerMember", PropertyBinder.instance(Integer.TYPE, "maxAdsPerMember"));
memberSettingsBinder.registerBinder("maxAdImagesPerMember", PropertyBinder.instance(Integer.TYPE, "maxAdImagesPerMember"));
memberSettingsBinder.registerBinder("defaultAdPublicationTime", DataBinderHelper.timePeriodBinder("defaultAdPublicationTime"));
memberSettingsBinder.registerBinder("maxAdPublicationTime", DataBinderHelper.timePeriodBinder("maxAdPublicationTime"));
memberSettingsBinder.registerBinder("enablePermanentAds", PropertyBinder.instance(Boolean.TYPE, "enablePermanentAds"));
memberSettingsBinder.registerBinder("externalAdPublication", PropertyBinder.instance(MemberGroupSettings.ExternalAdPublication.class, "externalAdPublication"));
memberSettingsBinder.registerBinder("maxAdDescriptionSize", PropertyBinder.instance(Integer.TYPE, "maxAdDescriptionSize"));
memberSettingsBinder.registerBinder("sendPasswordByEmail", PropertyBinder.instance(Boolean.TYPE, "sendPasswordByEmail"));
memberSettingsBinder.registerBinder("emailValidation", SimpleCollectionBinder.instance(EmailValidation.class, HashSet.class, "emailValidation"));
memberSettingsBinder.registerBinder("maxImagesPerMember", PropertyBinder.instance(Integer.TYPE, "maxImagesPerMember"));
memberSettingsBinder.registerBinder("viewLoansByGroup", PropertyBinder.instance(Boolean.TYPE, "viewLoansByGroup"));
memberSettingsBinder.registerBinder("repayLoanByGroup", PropertyBinder.instance(Boolean.TYPE, "repayLoanByGroup"));
memberSettingsBinder.registerBinder("maxSchedulingPayments", PropertyBinder.instance(Integer.TYPE, "maxSchedulingPayments"));
memberSettingsBinder.registerBinder("maxSchedulingPeriod", DataBinderHelper.timePeriodBinder("maxSchedulingPeriod"));
memberSettingsBinder.registerBinder("showPosWebPaymentDescription", PropertyBinder.instance(Boolean.TYPE, "showPosWebPaymentDescription"));
memberSettingsBinder.registerBinder("expireMembersAfter", DataBinderHelper.timePeriodBinder("expireMembersAfter"));
memberSettingsBinder.registerBinder("groupAfterExpiration", PropertyBinder.instance(MemberGroup.class, "groupAfterExpiration"));
}
private void initOperator(final BeanBinder<? extends OperatorGroup> operatorGroupBinder) {
// Bind max amount per day by transfer type map
final LocalSettings localSettings = settingsService.getLocalSettings();
final PropertyBinder<TransferType> keyBinder = PropertyBinder.instance(TransferType.class, "transferTypeIds");
final PropertyBinder<BigDecimal> valueBinder = PropertyBinder.instance(BigDecimal.class, "maxAmountPerDayByTT", localSettings.getNumberConverter());
final MapBinder<TransferType, BigDecimal> maxAmountBinder = MapBinder.instance(keyBinder, valueBinder);
operatorGroupBinder.registerBinder("maxAmountPerDayByTransferType", maxAmountBinder);
}
private void initSystem(final BeanBinder<? extends SystemGroup> groupBinder) {
groupBinder.registerBinder("rootUrl", PropertyBinder.instance(String.class, "rootUrl"));
groupBinder.registerBinder("loginPageName", PropertyBinder.instance(String.class, "loginPageName"));
groupBinder.registerBinder("containerUrl", PropertyBinder.instance(String.class, "containerUrl"));
}
private Group readBaseGroup(final ActionContext context) {
final EditGroupForm form = context.getForm();
final long baseGroupId = form.getBaseGroupId();
if (baseGroupId < 1) {
return null;
}
return groupService.load(baseGroupId);
}
private Group readGroup(final ActionContext context) {
final EditGroupForm form = context.getForm();
final long id = form.getGroupId();
Group.Nature nature;
final boolean isInsert = (id <= 0L);
if (isInsert) {
nature = getGroupNature(context, false);
// On insert, empty status means normal
final String status = (String) form.getGroup("status");
if (StringUtils.isEmpty(status)) {
form.setGroup("status", Group.Status.NORMAL.name());
}
} else {
nature = groupService.load(id).getNature();
}
final Group group = getDataBinder(nature).readFromString(form.getGroup());
if (nature == Nature.OPERATOR) {
// Ensure to set the logged member on operator groups, as this is not read from request
final Member member = (Member) context.getElement();
final OperatorGroup operatorGroup = (OperatorGroup) group;
operatorGroup.setMember(member);
}
return group;
}
}