package com.jay.demo;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;
import nl.t42.generic.EntityNotFoundException;
import nl.t42.generic.DomainEntity;
/**
* A that converts a HTTP request body to a , provided that
* the handler method argument is annotated with .
*/
public class PathEntityMethodArgumentResolver implements HandlerMethodArgumentResolver {
/**
* A conversion service to convert primary key values.
*/
@Autowired
private ConversionService conversionService;
/**
* The entity manager used to retrieve the entities.
*/
@Autowired
private EntityManager entityManager;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(PathEntity.class) && isADomainEntity(parameter);
}
/**
* Determine if a method parameter is a DomainEntity.
*
* @param parameter a method parameter
* @return if the type of the parameter is (a subclass of) DomainEntity
*/
protected boolean isADomainEntity(MethodParameter parameter) {
return DomainEntity.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public DomainEntity resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String primaryKeyName = getPrimaryKeyName(parameter);
Long entityId = findPrimaryKeyValue(webRequest, primaryKeyName);
return findEntity(parameter, entityId);
}
/**
* Get the nam of the URL template that holds the primary key.
*
* @param parameter the method parameter
* @return the name of a URL template
*/
protected String getPrimaryKeyName(MethodParameter parameter) {
return parameter.getParameterAnnotation(PathEntity.class).value();
}
private Long findPrimaryKeyValue(NativeWebRequest webRequest, String primaryKeyName) {
Map<String, String> pathVariables = getPathVariables(webRequest);
String primaryKeyValue = pathVariables.get(primaryKeyName);
if (primaryKeyValue == null) {
throw new IllegalStateException(String.format("The path variable %s cannot be resolved.", primaryKeyName));
}
return conversionService.convert(primaryKeyValue, Long.class);
}
private Map<String, String> getPathVariables(NativeWebRequest webRequest) {
HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return (Map<String, String>) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}
private DomainEntity findEntity(MethodParameter parameter, Long entityId) {
Class<? extends DomainEntity> entityType = (Class<? extends DomainEntity>) parameter.getParameterType();
DomainEntity entity = entityManager.find(entityType, entityId);
if (entity == null) {
throw new EntityNotFoundException(
String.format("Cannot find a %s with id=%d", entityType.getSimpleName(), entityId));
}
return entity;
}
}