package com.megatim.fdxcommons.core.impl.db.validators;
|
|
import static com.megatim.fdxcommons.model.enumeration.Operateur.*;
|
import com.megatim.fdxcommons.model.enumeration.TypeDonnee;
|
import com.megatim.fdxcommons.model.integration.ColumnDefinition;
|
import com.megatim.fdxcommons.model.pojo.BetweenOperatorValues;
|
import com.megatim.fdxcommons.model.pojo.CriteriaEntity;
|
import com.megatim.fdxcommons.tools.exceptions.CommonApplicationValidationException;
|
import java.math.BigDecimal;
|
import java.sql.Timestamp;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeParseException;
|
import java.util.ArrayList;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import javax.enterprise.context.Dependent;
|
import com.megatim.fdxcommons.core.ifaces.db.validators.CriteriaQueryValidator;
|
|
/**
|
*
|
* @author lenovo
|
*/
|
@Dependent
|
public class CriteriaQueryValidatorImpl implements CriteriaQueryValidator {
|
|
@Override
|
public List<String> validate(CriteriaEntity criterion, Map<String, ColumnDefinition> columnDefinitionsMap) {
|
List<String> errors = new ArrayList<>();
|
// int index = 1;
|
// String numeroElt = " : Elément numéro " + index;
|
TypeDonnee typeDonnee = null;
|
|
if (criterion != null && isNotEmptyCriteria(criterion)) {
|
if (criterion.getSubCriterias().isEmpty()) {
|
if (!validateCriteriaNomColonne(columnDefinitionsMap, criterion)) {
|
errors.add("Colonne '" + criterion.getNomColonne() + "' des critères de sélection est introuvable");
|
|
} else if ((typeDonnee = TypeDonnee.fromValeur(columnDefinitionsMap.get(criterion.getNomColonne().toLowerCase()).getTypeDonnee())) == null) {
|
errors.add("Le type de la colonne '" + criterion.getNomColonne() + "est introuvable");
|
|
} else if (!validateCriteriaEntityValue(criterion, typeDonnee)) {
|
errors.add("Type de données de la colonne " + criterion.getNomColonne() + " incorrect");
|
}
|
} else {
|
if (criterion.getCriteriaLogicConnector() == null) {
|
errors.add("Le connecteur logique est absent");
|
}
|
for (CriteriaEntity c : criterion.getSubCriterias()) {
|
errors.addAll(validate(c, columnDefinitionsMap));
|
}
|
}
|
}
|
return errors;
|
}
|
|
private boolean validateCriteriaNomColonne(Map<String, ColumnDefinition> columnDefinitionsMap, CriteriaEntity c) {
|
return c.getNomColonne() != null
|
&& !c.getNomColonne().isEmpty()
|
&& columnDefinitionsMap.containsKey(c.getNomColonne().toLowerCase());
|
}
|
|
private boolean validateCriteriaEntityValue(CriteriaEntity criteriaEntity, TypeDonnee typeDonnee) {
|
switch (criteriaEntity.getOperateur()) {
|
case LIKE:
|
return (criteriaEntity.getCriteriaValue() instanceof String) && columTypeIsString(typeDonnee);
|
case IN:
|
case NOT_IN:
|
return (criteriaEntity.getCriteriaValue() instanceof List<?>) && elementsOfList((List) criteriaEntity.getCriteriaValue(), typeDonnee);
|
case LOWER_OR_EQUALS_THAN:
|
case LOWER_THAN:
|
case GREATER_OR_EQUALS_THAN:
|
case GREATER_THAN:
|
case EQUALS:
|
case NOT_EQUALS:
|
return (criteriaEntity.getCriteriaValue() instanceof Comparable<?>) && criteriaValueHasCorrectType(criteriaEntity.getCriteriaValue(), typeDonnee);
|
case BETWEEN:
|
case NOT_BETWEEN:
|
BetweenOperatorValues betweenOperatorValues = getBetweenOperatorValues(criteriaEntity.getCriteriaValue());
|
criteriaEntity.setCriteriaValue(betweenOperatorValues);
|
|
return betweenOperatorValues != null
|
&& criteriaValueHasCorrectType(betweenOperatorValues.getLowerBound(), typeDonnee)
|
&& criteriaValueHasCorrectType(betweenOperatorValues.getUpperBound(), typeDonnee)
|
&& betweenOperatorValuesAreCorrect(betweenOperatorValues, typeDonnee);
|
case IS_NULL:
|
case IS_NOT_NULL:
|
return criteriaEntity.getCriteriaValue() == null;
|
}
|
return false;
|
}
|
|
@Override
|
public BetweenOperatorValues getBetweenOperatorValues(Object value) {
|
BetweenOperatorValues betweenOperatorValues = null;
|
if (!(value instanceof LinkedHashMap)) {
|
throw new CommonApplicationValidationException("LinkedHashMap est attendu");
|
}
|
LinkedHashMap<String, String> map = (LinkedHashMap) value;
|
String lowerBound = null;
|
String upperBound = null;
|
|
for (String key : map.keySet()) {
|
if (key.equalsIgnoreCase("lowerBound")) {
|
lowerBound = map.get(key);
|
}
|
if (key.equalsIgnoreCase("upperBound")) {
|
upperBound = map.get(key);
|
}
|
}
|
StringBuilder message = new StringBuilder("");
|
|
if (lowerBound == null) {
|
message.append("Borne inférieure absente\n");
|
}
|
if (upperBound == null) {
|
message.append("Borne supérieure absente");
|
}
|
if (message.length() > 0) {
|
throw new CommonApplicationValidationException(message.toString());
|
}
|
betweenOperatorValues = new BetweenOperatorValues(lowerBound, upperBound);
|
|
return betweenOperatorValues;
|
}
|
|
/**
|
* Vérifier que le borne inférieure est bel et bien inférieure à la borne
|
* supérieure
|
*
|
* @param betweenOperatorValues
|
* @param columnType
|
* @return
|
*/
|
private boolean betweenOperatorValuesAreCorrect(BetweenOperatorValues betweenOperatorValues, TypeDonnee typeDonnee) {
|
boolean result = false;
|
switch (typeDonnee) {
|
|
case NUMERIQUE:
|
try {
|
Long lowerBound = Long.valueOf(betweenOperatorValues.getLowerBound().toString());
|
Long upperBound = Long.valueOf(betweenOperatorValues.getUpperBound().toString());
|
|
result = lowerBound <= upperBound;
|
if (!result) {
|
throw new CommonApplicationValidationException("La borne inférieure ne peut être supérieure à la borne supérieure");
|
}
|
} catch (NumberFormatException ex) {
|
}
|
break;
|
|
case DECIMAL:
|
try {
|
BigDecimal lowerBound = new BigDecimal(betweenOperatorValues.getLowerBound().toString());
|
BigDecimal upperBound = new BigDecimal(betweenOperatorValues.getUpperBound().toString());
|
|
result = lowerBound.compareTo(upperBound) <= 0;
|
if (!result) {
|
throw new CommonApplicationValidationException("La borne inférieure ne peut être supérieure à la borne supérieure");
|
}
|
} catch (NumberFormatException ex) {
|
}
|
break;
|
|
case DATE:
|
try {
|
Timestamp lowerBound = Timestamp.valueOf(LocalDateTime.parse(betweenOperatorValues.getLowerBound().toString()));
|
Timestamp upperBound = Timestamp.valueOf(LocalDateTime.parse(betweenOperatorValues.getUpperBound().toString()));
|
|
result = lowerBound.before(upperBound);
|
if (!result) {
|
throw new CommonApplicationValidationException("La borne inférieure ne peut être supérieure à la borne supérieure");
|
}
|
} catch (DateTimeParseException ex) {
|
}
|
break;
|
|
default:
|
throw new CommonApplicationValidationException("L'opérarateur 'BETWEEN' n'est pas valable pour ce type de données " + typeDonnee);
|
|
}
|
return result;
|
}
|
|
private boolean elementsOfList(List<?> elements, TypeDonnee typeDonnee) {
|
boolean result = true;
|
|
for (Object elt : elements) {
|
result = criteriaValueHasCorrectType(elt, typeDonnee);
|
|
if (!result) {
|
break;
|
}
|
}
|
return result;
|
}
|
|
private boolean criteriaValueHasCorrectType(Object value, TypeDonnee typeDonnee) {
|
boolean result = false;
|
|
switch (typeDonnee) {
|
case NUMERIQUE:
|
try {
|
Long.valueOf(value.toString());
|
result = true;
|
} catch (NumberFormatException ex) {
|
}
|
break;
|
|
case DECIMAL:
|
try {
|
new BigDecimal(value.toString());
|
result = true;
|
} catch (Exception ex) {
|
}
|
break;
|
|
case DATE:
|
try {
|
Timestamp.valueOf(LocalDateTime.parse(value.toString()));
|
result = true;
|
} catch (IllegalArgumentException ex) {
|
}
|
break;
|
|
case ALPHANUMERIQUE:
|
result = value instanceof String;
|
break;
|
|
default:
|
throw new CommonApplicationValidationException("Type de données inconnu");
|
}
|
return result;
|
}
|
|
private boolean columTypeIsString(TypeDonnee typeDonnee) {
|
return typeDonnee.equals(TypeDonnee.ALPHANUMERIQUE);
|
}
|
|
private boolean isNotEmptyCriteria(CriteriaEntity c) {
|
return c.getNomColonne() != null && !c.getNomColonne().isEmpty() && c.getOperateur() != null
|
|| c.getSubCriterias() != null && !c.getSubCriterias().isEmpty();
|
}
|
}
|