/*
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.elements;
import nl.strohalm.cyclos.controls.ActionContext;
import nl.strohalm.cyclos.controls.BaseBindingForm;
import nl.strohalm.cyclos.controls.BaseFormAction;
import nl.strohalm.cyclos.entities.access.User;
import nl.strohalm.cyclos.entities.customization.fields.CustomField;
import nl.strohalm.cyclos.entities.customization.fields.CustomFieldValue;
import nl.strohalm.cyclos.entities.customization.fields.MemberCustomFieldValue;
import nl.strohalm.cyclos.entities.groups.Group;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.settings.AccessSettings;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import nl.strohalm.cyclos.services.elements.exceptions.NoInitialGroupException;
import nl.strohalm.cyclos.services.elements.exceptions.UsernameAlreadyInUseException;
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.ReferenceConverter;
import nl.strohalm.cyclos.utils.validation.PasswordsDontMatchError;
import nl.strohalm.cyclos.utils.validation.ValidationException;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionForward;
/**
* Action used to create an element
* @author luis
*/
public abstract class CreateElementAction<E extends Element> extends BaseFormAction {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <E extends Element> DataBinder<E> getDataBinder(final LocalSettings localSettings, final AccessSettings accessSettings, final Class<E> elementClass, final Class userClass, final Class groupClass, final Class customField, final Class customFieldValue) {
final BeanBinder<? extends CustomFieldValue> customValueBinder = BeanBinder.instance(customFieldValue);
customValueBinder.registerBinder("field", PropertyBinder.instance(customField, "field", ReferenceConverter.instance(customField)));
customValueBinder.registerBinder("value", PropertyBinder.instance(String.class, "value", HtmlConverter.instance()));
if (MemberCustomFieldValue.class.isAssignableFrom(customFieldValue)) {
customValueBinder.registerBinder("hidden", PropertyBinder.instance(Boolean.TYPE, "hidden"));
}
final BeanBinder<E> elementBinder = BeanBinder.instance(elementClass);
elementBinder.registerBinder("name", PropertyBinder.instance(String.class, "name"));
elementBinder.registerBinder("email", PropertyBinder.instance(String.class, "email"));
if (Member.class.isAssignableFrom(elementClass)) {
elementBinder.registerBinder("hideEmail", PropertyBinder.instance(Boolean.TYPE, "hideEmail"));
}
elementBinder.registerBinder("group", PropertyBinder.instance(groupClass, "group", ReferenceConverter.instance(groupClass)));
elementBinder.registerBinder("customValues", BeanCollectionBinder.instance(customValueBinder, "customValues"));
final BeanBinder<? extends User> userBinder = BeanBinder.instance(userClass, "user");
if (!(Member.class.isAssignableFrom(elementClass) && accessSettings.isUsernameGenerated())) {
userBinder.registerBinder("username", PropertyBinder.instance(String.class, "username"));
}
userBinder.registerBinder("password", PropertyBinder.instance(String.class, "password"));
elementBinder.registerBinder("user", userBinder);
return elementBinder;
}
protected DataBinder<? extends Element> dataBinder;
public DataBinder<? extends Element> getDataBinder() {
if (dataBinder == null) {
dataBinder = getBaseBinder();
}
return dataBinder;
}
/**
* Should be overriden to create the element
*/
protected abstract ActionForward create(Element element, ActionContext context);
protected DataBinder<? extends Element> getBaseBinder() {
final LocalSettings localSettings = settingsService.getLocalSettings();
final AccessSettings accessSettings = settingsService.getAccessSettings();
return getDataBinder(localSettings, accessSettings, getElementClass(), getUserClass(), getGroupClass(), getCustomFieldClass(), getCustomFieldValueClass());
}
protected abstract <CF extends CustomField> Class<CF> getCustomFieldClass();
protected abstract <CFV extends CustomFieldValue> Class<CFV> getCustomFieldValueClass();
protected abstract Class<E> getElementClass();
protected abstract <G extends Group> Class<G> getGroupClass();
protected abstract <U extends User> Class<U> getUserClass();
@Override
protected ActionForward handleDisplay(final ActionContext context) throws Exception {
try {
prepareForm(context);
} catch (final NoInitialGroupException e) {
return context.sendError("createMember.error.noInitialGroup");
}
return context.getInputForward();
}
@Override
protected ActionForward handleSubmit(final ActionContext context) throws Exception {
final BaseBindingForm form = context.getForm();
final Element element = getDataBinder().readFromString(form.getValues());
element.setGroup(groupService.load(element.getGroup().getId()));
ActionForward forward;
try {
forward = create(element, context);
} catch (final NoInitialGroupException e) {
return context.sendError("createMember.error.noInitialGroup");
} catch (final UsernameAlreadyInUseException e) {
return context.sendError("createMember.error.usernameAlreadyInUse", e.getUsername());
}
return forward == null ? context.getSuccessForward() : forward;
}
protected abstract void runValidation(final ActionContext context, final Element element);
@Override
protected void validateForm(final ActionContext context) {
final CreateElementForm form = context.getForm();
final Element element = getDataBinder().readFromString(form.getValues());
ValidationException exc;
try {
runValidation(context, element);
exc = new ValidationException();
} catch (final ValidationException e) {
exc = e;
}
String password;
try {
password = StringUtils.trimToNull(element.getUser().getPassword());
} catch (final Exception e) {
password = null;
}
final String confirmPassword = StringUtils.trimToNull(form.getConfirmPassword());
if (password != null && (confirmPassword == null || !ObjectUtils.equals(confirmPassword, element.getUser().getPassword()))) {
exc.addGeneralError(new PasswordsDontMatchError());
}
exc.throwIfHasErrors();
}
}