/*
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.records;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import nl.strohalm.cyclos.access.AdminAdminPermission;
import nl.strohalm.cyclos.access.AdminMemberPermission;
import nl.strohalm.cyclos.access.BrokerPermission;
import nl.strohalm.cyclos.annotations.Inject;
import nl.strohalm.cyclos.controls.ActionContext;
import nl.strohalm.cyclos.controls.BaseFormAction;
import nl.strohalm.cyclos.entities.customization.fields.CustomFieldValue;
import nl.strohalm.cyclos.entities.customization.fields.MemberRecordCustomField;
import nl.strohalm.cyclos.entities.customization.fields.MemberRecordCustomFieldValue;
import nl.strohalm.cyclos.entities.groups.AdminGroup;
import nl.strohalm.cyclos.entities.groups.BrokerGroup;
import nl.strohalm.cyclos.entities.groups.Group;
import nl.strohalm.cyclos.entities.members.Administrator;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.records.MemberRecord;
import nl.strohalm.cyclos.entities.members.records.MemberRecordType;
import nl.strohalm.cyclos.entities.members.records.MemberRecordType.Layout;
import nl.strohalm.cyclos.services.customization.MemberRecordCustomFieldService;
import nl.strohalm.cyclos.services.elements.MemberRecordService;
import nl.strohalm.cyclos.services.elements.MemberRecordTypeService;
import nl.strohalm.cyclos.utils.ActionHelper;
import nl.strohalm.cyclos.utils.CustomFieldHelper;
import nl.strohalm.cyclos.utils.CustomFieldHelper.Entry;
import nl.strohalm.cyclos.utils.Navigation;
import nl.strohalm.cyclos.utils.binding.BeanBinder;
import nl.strohalm.cyclos.utils.binding.BeanCollectionBinder;
import nl.strohalm.cyclos.utils.binding.DataBinder;
import nl.strohalm.cyclos.utils.binding.PropertyBinder;
import nl.strohalm.cyclos.utils.conversion.HtmlConverter;
import nl.strohalm.cyclos.utils.conversion.IdConverter;
import nl.strohalm.cyclos.utils.validation.ValidationException;
import org.apache.struts.action.ActionForward;
/**
* Action used to edit a member record
* @author Jefferson Magno
*/
public class EditMemberRecordAction extends BaseFormAction {
private MemberRecordCustomFieldService memberRecordCustomFieldService;
private MemberRecordService memberRecordService;
private MemberRecordTypeService memberRecordTypeService;
private DataBinder<MemberRecord> dataBinder;
private CustomFieldHelper customFieldHelper;
public MemberRecordService getMemberRecordService() {
return memberRecordService;
}
@Inject
public void setCustomFieldHelper(final CustomFieldHelper customFieldHelper) {
this.customFieldHelper = customFieldHelper;
}
@Inject
public void setMemberRecordCustomFieldService(final MemberRecordCustomFieldService memberRecordCustomFieldService) {
this.memberRecordCustomFieldService = memberRecordCustomFieldService;
}
@Inject
public void setMemberRecordService(final MemberRecordService memberRecordService) {
this.memberRecordService = memberRecordService;
}
@Inject
public void setMemberRecordTypeService(final MemberRecordTypeService memberRecordTypeService) {
this.memberRecordTypeService = memberRecordTypeService;
}
@Override
protected ActionForward handleSubmit(final ActionContext context) throws Exception {
final EditMemberRecordForm form = context.getForm();
MemberRecord memberRecord = getDataBinder().readFromString(form.getMemberRecord());
final boolean isInsert = memberRecord.isTransient();
if (isInsert) {
memberRecord = memberRecordService.insert(memberRecord);
} else {
memberRecord = memberRecordService.update(memberRecord);
}
if (isInsert) {
context.sendMessage("memberRecord.inserted");
} else {
context.sendMessage("memberRecord.modified");
}
final boolean isFlat = memberRecord.getType().getLayout() == Layout.FLAT;
ActionForward forward;
final Navigation navigation = context.getNavigation();
final String last = navigation.getPrevious();
if (last != null && last.contains("/search")) {
forward = context.findForward("successList");
} else {
if (isFlat) {
forward = context.findForward("successFlat");
} else {
forward = context.getSuccessForward();
}
}
final Map<String, Object> params = new HashMap<String, Object>();
params.put("memberRecordId", memberRecord.getId());
final SearchMemberRecordsForm searchForm = (SearchMemberRecordsForm) context.getSession().getAttribute("searchMemberRecordsForm");
if (searchForm == null || !searchForm.isGlobal()) {
params.put("elementId", memberRecord.getElement().getId());
}
params.put("typeId", memberRecord.getType().getId());
forward = ActionHelper.redirectWithParams(context.getRequest(), forward, params);
if (isFlat) {
// Go directly to the anchor
forward.setPath(forward.getPath() + "#memberRecord_" + memberRecord.getId());
}
return forward;
}
@Override
protected void prepareForm(final ActionContext context) throws Exception {
final HttpServletRequest request = context.getRequest();
final EditMemberRecordForm form = context.getForm();
MemberRecordType type = null;
Element element = null;
final long memberRecordId = form.getMemberRecordId();
MemberRecord memberRecord;
final boolean isInsert = memberRecordId <= 0L;
if (isInsert) {
request.setAttribute("isInsert", true);
memberRecord = new MemberRecord();
final long baseMemberRecordId = form.getBaseMemberRecordId();
if (baseMemberRecordId > 0) {
// Copying data from an existing member record
final MemberRecord baseMemberRecord = memberRecordService.load(baseMemberRecordId, MemberRecord.Relationships.TYPE, MemberRecord.Relationships.ELEMENT, MemberRecord.Relationships.CUSTOM_VALUES);
type = baseMemberRecord.getType();
element = baseMemberRecord.getElement();
// Clone custom values
customFieldHelper.cloneFieldValues(baseMemberRecord, memberRecord);
request.setAttribute("baseMemberRecord", baseMemberRecord);
}
memberRecord.setType(type);
memberRecord.setElement(element);
} else {
memberRecord = memberRecordService.load(memberRecordId, MemberRecord.Relationships.BY, MemberRecord.Relationships.MODIFIED_BY, MemberRecord.Relationships.CUSTOM_VALUES, MemberRecord.Relationships.ELEMENT);
type = memberRecord.getType();
element = memberRecord.getElement();
request.setAttribute("memberRecord", memberRecord);
}
if (type == null) {
final long typeId = form.getTypeId();
if (typeId <= 0L) {
throw new ValidationException();
}
type = memberRecordTypeService.load(typeId);
}
if (element == null) {
final long elementId = form.getElementId();
if (elementId <= 0L) {
throw new ValidationException();
}
element = elementService.load(elementId);
}
final boolean byBroker = (element instanceof Member) && context.isBrokerOf((Member) element);
request.setAttribute("element", element);
request.setAttribute("byBroker", byBroker);
request.setAttribute("type", type);
request.setAttribute("global", form.isGlobal());
// Get custom field entries
final List<MemberRecordCustomField> customFields = memberRecordCustomFieldService.list(type);
if (byBroker) {
final Collection<MemberRecordCustomField> readOnlyFields = new HashSet<MemberRecordCustomField>();
for (final Iterator<MemberRecordCustomField> iterator = customFields.iterator(); iterator.hasNext();) {
final MemberRecordCustomField field = iterator.next();
switch (field.getBrokerAccess()) {
case NONE:
iterator.remove();
break;
case READ_ONLY:
if (isInsert) {
iterator.remove();
} else {
readOnlyFields.add(field);
}
break;
}
}
request.setAttribute("readOnlyFields", readOnlyFields);
}
request.setAttribute("customFields", customFields);
final Collection<Entry> entries = customFieldHelper.buildEntries(customFields, memberRecord.getCustomValues());
request.setAttribute("customFieldEntries", entries);
// Check permissions for logged user
final Group group = context.getGroup();
boolean canCreate = false;
boolean canModify = false;
boolean canDelete = false; // This attribute is used on FlatMemberRecordsAction that inherits from this class
if (context.isAdmin()) {
AdminGroup adminGroup = (AdminGroup) group;
adminGroup = groupService.load(adminGroup.getId(), AdminGroup.Relationships.CREATE_MEMBER_RECORD_TYPES, AdminGroup.Relationships.MODIFY_MEMBER_RECORD_TYPES, AdminGroup.Relationships.DELETE_MEMBER_RECORD_TYPES, AdminGroup.Relationships.CREATE_ADMIN_RECORD_TYPES, AdminGroup.Relationships.MODIFY_ADMIN_RECORD_TYPES, AdminGroup.Relationships.DELETE_ADMIN_RECORD_TYPES);
if (element instanceof Member) {
canCreate = permissionService.hasPermission(AdminMemberPermission.RECORDS_CREATE) && adminGroup.getCreateMemberRecordTypes().contains(type);
canModify = permissionService.hasPermission(AdminMemberPermission.RECORDS_MODIFY) && adminGroup.getModifyMemberRecordTypes().contains(type);
canDelete = permissionService.hasPermission(AdminMemberPermission.RECORDS_DELETE) && adminGroup.getDeleteMemberRecordTypes().contains(type);
} else if (element instanceof Administrator) {
canCreate = permissionService.hasPermission(AdminAdminPermission.RECORDS_CREATE) && adminGroup.getCreateAdminRecordTypes().contains(type);
canModify = permissionService.hasPermission(AdminAdminPermission.RECORDS_MODIFY) && adminGroup.getModifyAdminRecordTypes().contains(type);
canDelete = permissionService.hasPermission(AdminAdminPermission.RECORDS_DELETE) && adminGroup.getDeleteAdminRecordTypes().contains(type);
}
} else if ((element instanceof Member) && context.isBrokerOf((Member) element)) {
BrokerGroup brokerGroup = (BrokerGroup) group;
brokerGroup = groupService.load(brokerGroup.getId(), BrokerGroup.Relationships.BROKER_CREATE_MEMBER_RECORD_TYPES, BrokerGroup.Relationships.BROKER_MODIFY_MEMBER_RECORD_TYPES);
canCreate = permissionService.hasPermission(BrokerPermission.MEMBER_RECORDS_CREATE) && brokerGroup.getBrokerCreateMemberRecordTypes().contains(type);
canModify = permissionService.hasPermission(BrokerPermission.MEMBER_RECORDS_MODIFY) && brokerGroup.getBrokerModifyMemberRecordTypes().contains(type);
canDelete = permissionService.hasPermission(BrokerPermission.MEMBER_RECORDS_DELETE) && brokerGroup.getBrokerDeleteMemberRecordTypes().contains(type);
}
request.setAttribute("canCreate", canCreate);
request.setAttribute("canModify", canModify);
request.setAttribute("canDelete", canDelete);
}
private DataBinder<MemberRecord> getDataBinder() {
if (dataBinder == null) {
final BeanBinder<? extends CustomFieldValue> customValueBinder = BeanBinder.instance(MemberRecordCustomFieldValue.class);
customValueBinder.registerBinder("field", PropertyBinder.instance(MemberRecordCustomField.class, "field"));
customValueBinder.registerBinder("value", PropertyBinder.instance(String.class, "value", HtmlConverter.instance()));
final BeanBinder<MemberRecord> binder = BeanBinder.instance(MemberRecord.class);
binder.registerBinder("id", PropertyBinder.instance(Long.class, "id", IdConverter.instance()));
binder.registerBinder("type", PropertyBinder.instance(MemberRecordType.class, "type"));
binder.registerBinder("element", PropertyBinder.instance(Element.class, "element"));
binder.registerBinder("customValues", BeanCollectionBinder.instance(customValueBinder, "customValues"));
dataBinder = binder;
}
return dataBinder;
}
}