package de.ppi.fuwesta.oval.validation;
import static org.fest.reflect.core.Reflection.field;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import net.sf.oval.Validator;
import net.sf.oval.configuration.annotation.AbstractAnnotationCheck;
import net.sf.oval.context.OValContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import de.ppi.fuwesta.jpa.helper.JpaQueryExecutor;
/**
* Check which validates whether one property or a set of properties is unique.
*
*/
public class OptimisticLockCheck extends
AbstractAnnotationCheck<OptimisticLock> {
/** The primary key column. */
private String versionColumn = "version";
/** The primary key column. */
private String primaryKeyColumn = "id";
/** The primary key column. */
private String optimisiticLockingViolatedColumn =
"optimisiticLockingViolated";
/**
* The default message-key.
*/
static final String MESSAGE = "validation.optimistic.lock";
/**
* Helper to runs JPA-Queries.
*/
@Autowired
private transient JpaQueryExecutor jpa;
/**
* Instantiates a new unique check.
*/
public OptimisticLockCheck() {
setMessage(MESSAGE);
}
@Override
public void configure(OptimisticLock constraintAnnotation) {
setMessage(constraintAnnotation.message());
primaryKeyColumn = constraintAnnotation.primaryKeyColumn();
versionColumn = constraintAnnotation.value();
}
@Override
public Map<String, String> createMessageVariables() {
Map<String, String> messageVariables = new HashMap<String, String>();
messageVariables.put("reloadUrl", getReloadUrl());
return messageVariables;
}
/**
*
* {@inheritDoc}
*/
@Override
public boolean isSatisfied(Object validatedObject, Object value,
OValContext context, Validator validator) {
requireMessageVariablesRecreation();
final Object model = validatedObject;
final Object keyValue =
field(primaryKeyColumn).ofType(Object.class).in(model).get();
final Long versionValue =
field(versionColumn).ofType(Long.class).in(model).get();
@SuppressWarnings("boxing")
final boolean optimisiticLockingViolated =
field(optimisiticLockingViolatedColumn).ofType(boolean.class)
.in(model).get();
final String entityName = model.getClass().getName();
if (optimisiticLockingViolated) {
return false;
}
if (keyValue != null) {
if (versionValue == null) {
return false;
} else {
String jpql =
"select m.version from " + entityName
+ " as m where m.id = ?";
final Long dbVersion =
(Long) jpa.queryWithSingleResult(jpql, keyValue);
if (dbVersion.longValue() > versionValue.longValue()) {
return false;
}
}
}
return true;
}
/**
* Search for the current request-url.
*
* @return the current request-url.
*/
private String getReloadUrl() {
final RequestAttributes rq =
RequestContextHolder.currentRequestAttributes();
String reloadURL = null;
if (rq instanceof ServletRequestAttributes) {
final ServletRequestAttributes sra = (ServletRequestAttributes) rq;
final HttpServletRequest request = sra.getRequest();
reloadURL = request.getHeader("referer");
if (StringUtils.isEmpty(reloadURL)) {
reloadURL = request.getRequestURL().toString();
}
}
return reloadURL;
}
}