AbstractUploadListener.java
package sk.iway.iwcm.admin;
import org.springframework.beans.BeanUtils;
import org.springframework.core.GenericTypeResolver;
import org.springframework.ui.ModelMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.system.spring.events.WebjetEvent;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Abstraktna trieda ktora spracuje multipart upload v MVC aplikacii vo WebJET CMS
* Vysledkom je vrateny objekt form aj s pripojenym suborom
*/
public abstract class AbstractUploadListener<T> {
private final Validator validator;
private BindingResult bindingResult;
private boolean isPost;
private T form;
protected AbstractUploadListener(Validator validator) {
this.validator = validator;
}
/**
* Metoda pre sprocesovanie formularu a validovanie
* @param event WebjetEvent<ThymeleafEvent>
*/
public void processForm(final WebjetEvent<ThymeleafEvent> event) {
ModelMap model = event.getSource().getModel();
this.isPost = "post".equalsIgnoreCase(event.getSource().getRequest().getMethod());
Optional<T> formOptional = getBeanOptional(event.getSource().getRequest());
if (!formOptional.isPresent()) {
return;
}
this.form = formOptional.get();
this.bindingResult = new BeanPropertyBindingResult(form, "form");
validate(model, form);
}
/**
* Metoda pre validaciu dat z formularu
* @param model ModelMap
* @param form T
*/
public void validate(ModelMap model, T form) {
if (!isPost) {
return;
}
Set<ConstraintViolation<T>> violations = validator.validate(form);
//we dont know why, but validator for files returns same error two times
Set<String> duplicityCheck = new HashSet<>();
for (ConstraintViolation<T> violation : violations) {
String message = violation.getMessage();
String path = violation.getPropertyPath().toString();
String key = path + "_" + message;
if (duplicityCheck.contains(key)) {
continue;
}
duplicityCheck.add(key);
this.bindingResult.rejectValue(path, "", message);
}
model.put(BindingResult.MODEL_KEY_PREFIX + "form", this.bindingResult);
}
/**
* Pomocna metoda pre ziskanie informacie, ci je request typu post
* @return boolean
*/
public boolean isPost() {
return isPost;
}
/**
* Pomocna metoda pre ziskanie vysledku validacii
* @return BindingResult
*/
public BindingResult getBindingResult() {
return bindingResult;
}
/**
* Pomocna metoda pre ziskanie objektu s vyplnenymi datami vo formulari
* @return T
*/
public T getForm() {
return form;
}
/**
* Metoda pre ziskanie dat z requestu a nasetovanie do generickeho objektu
* @param request HttpServletRequest
* @return Optional<T>
*/
private Optional<T> getBeanOptional(HttpServletRequest request) {
//noinspection unchecked
@SuppressWarnings("unchecked")
Class<T> tClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), AbstractUploadListener.class);
if (tClass == null) {
Logger.error(AbstractUploadListener.class, "Cannot resolve type argument of this class: {}", getClass());
return Optional.empty();
}
T instance = BeanUtils.instantiateClass(tClass);
if (!isPost) {
return Optional.of(instance);
}
setParametersToProperties(request, instance);
setMultipartFilePerametersToProperties(request, instance);
return Optional.of(instance);
}
/**
* Metoda pre nasavenie hodnot z formularu do properties objektu
* @param request HttpServletRequest
* @param form T
*/
private void setParametersToProperties(HttpServletRequest request, T form) {
Map<String, String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> stringEntry : parameterMap.entrySet()) {
setProperty(request, form, stringEntry.getKey());
}
}
/**
* Metoda pre nasavenie hodnoty z formularu do property objektu
* @param request HttpServletRequest
* @param form T
* @param key String
*/
private void setProperty(HttpServletRequest request, T form, String key) {
Method declaredMethodWithMinimalParameters = BeanUtils.findDeclaredMethodWithMinimalParameters(form.getClass(), "set" + StringUtils.capitalize(key));
if (declaredMethodWithMinimalParameters == null) {
return;
}
try {
declaredMethodWithMinimalParameters.invoke(form, Tools.getParameter(request, key));
} catch (IllegalAccessException | InvocationTargetException e) {
sk.iway.iwcm.Logger.error(e);
}
}
/**
* Metoda pre vlozenie suborov z formularu do properties objektu
* @param request HttpServletRequest
* @param form T
*/
private void setMultipartFilePerametersToProperties(HttpServletRequest request, T form) {
if (!request.getClass().isAssignableFrom(DefaultMultipartHttpServletRequest.class)) {
return;
}
DefaultMultipartHttpServletRequest req = (DefaultMultipartHttpServletRequest) request;
MultiValueMap<String, MultipartFile> multiFileMap = req.getMultiFileMap();
for (Map.Entry<String, List<MultipartFile>> stringListEntry : multiFileMap.entrySet()) {
String key = stringListEntry.getKey();
List<MultipartFile> value = stringListEntry.getValue();
for (MultipartFile multipartFile : value) {
if (multipartFile.getSize() == 0) {
continue;
}
Method declaredMethodWithMinimalParameters = BeanUtils.findDeclaredMethod(form.getClass(), "set" + StringUtils.capitalize(key), MultipartFile.class);
if (declaredMethodWithMinimalParameters == null) {
continue;
}
try {
declaredMethodWithMinimalParameters.invoke(form, multipartFile);
} catch (IllegalAccessException | InvocationTargetException e) {
sk.iway.iwcm.Logger.error(e);
}
}
}
}
}