/*
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
*/
|
package com.megatim.fdxcommons.tools.database.queries.metadata.jpql;
|
|
import com.megatim.fdxcommons.model.enumeration.Operateur;
|
import com.megatim.fdxcommons.model.search.EnumValue;
|
import com.megatim.fdxcommons.tools.database.exceptions.BadQueryCriteriaException;
|
import java.lang.reflect.Field;
|
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Method;
|
import java.lang.reflect.Modifier;
|
import java.sql.Timestamp;
|
import java.time.LocalDateTime;
|
import java.time.LocalTime;
|
import java.time.ZonedDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
import java.util.Optional;
|
import java.util.logging.Level;
|
import java.util.logging.Logger;
|
|
/**
|
*
|
* @author ASUS
|
*/
|
public class JpqlParsedQueryCriterion {
|
|
private final JpqlQueryCriterion queryCriterion;
|
private final Class<?> classe;
|
|
public JpqlParsedQueryCriterion(JpqlQueryCriterion queryCriterion, Class<?> classe) {
|
this.queryCriterion = queryCriterion;
|
this.classe = classe;
|
}
|
|
public JpqlQueryCriterion parsedCriterion() throws Exception {
|
return queryCriterion != null
|
? parsedCriterion(queryCriterion)
|
: null;
|
}
|
|
private JpqlQueryCriterion parsedCriterion(JpqlQueryCriterion criterion) throws Exception {
|
|
if (criterion.getSubCriteria() != null && !criterion.getSubCriteria().isEmpty() && criterion.getCriteriaLogicConnector() != null) {
|
List<JpqlQueryCriterion> subCriteria = new ArrayList<>();
|
|
for (JpqlQueryCriterion qc : criterion.getSubCriteria()) {
|
JpqlQueryCriterion parsedCriterion = parsedCriterion(qc);
|
|
if (parsedCriterion != null) {
|
subCriteria.add(parsedCriterion);
|
}
|
}
|
if (!subCriteria.isEmpty()) {
|
return new JpqlQueryCriterion(null,
|
null,
|
null,
|
criterion.getCriteriaLogicConnector(),
|
subCriteria,
|
criterion.isEndOfTheDay()
|
);
|
}
|
} else if ((criterion.getSubCriteria() == null || criterion.getSubCriteria().isEmpty())
|
&& criterion.getNomColonne() != null && !criterion.getNomColonne().isEmpty() && criterion.getOperateur() != null) {
|
Class<?> clazz = columnType(criterion.getNomColonne());
|
|
if (clazz != null) {
|
|
Object correctValue = correctValue(clazz, criterion);
|
|
if (isUnaryOperator(criterion.getOperateur()) || (correctValue != null && !correctValue.toString().isEmpty())) {
|
return new JpqlQueryCriterion(criterion.getNomColonne(),
|
correctValue,
|
criterion.getOperateur(),
|
null,
|
Arrays.asList(),
|
criterion.isEndOfTheDay()
|
);
|
}
|
}
|
}
|
return null;
|
}
|
|
private Class<?> columnType(String nomColonne) {
|
Field[] fields = classe.getDeclaredFields();
|
String[] fieldPath = nomColonne.split("\\.");
|
try {
|
return columnType(fieldPath, fields);
|
} catch (BadQueryCriteriaException ex) {
|
Logger.getLogger(JpqlParsedQueryCriterion.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
|
return null;
|
}
|
}
|
|
private Class<?> columnType(String[] fieldPath, Field[] fields) throws BadQueryCriteriaException {
|
Optional<Field> optField = Arrays.asList(fields).stream().filter(f -> f.getName().equals(fieldPath[0])).findFirst();
|
|
if (optField.isPresent()) {
|
if (fieldPath.length == 1) {
|
return optField.get().getType();
|
} else {
|
return columnType(Arrays.copyOfRange(fieldPath, 1, fieldPath.length), optField.get().getType().getDeclaredFields());
|
}
|
} else {
|
throw new BadQueryCriteriaException("Colonne " + fields[0] + " introuvable dans la classe " + optField.get().getDeclaringClass().getName());
|
|
}
|
}
|
|
private Object correctValue(Class<?> clazz, JpqlQueryCriterion criterion) throws IllegalAccessException, BadQueryCriteriaException, IllegalArgumentException, InvocationTargetException {
|
|
Object criteriaValue = criterion.getCriteriaValue();
|
if (criteriaValue == null) {
|
return null;
|
}
|
|
if (clazz.isEnum()) {
|
|
Method[] methods = clazz.getMethods();
|
Optional<Method> optionalMethod = Arrays.asList(methods)
|
.stream()
|
.filter(m -> m.getAnnotation(EnumValue.class) != null && Modifier.isStatic(m.getModifiers())).findFirst();
|
|
if (optionalMethod.isPresent()) {
|
Method method = optionalMethod.get();
|
return method.invoke(null, criteriaValue.toString());
|
}
|
|
return criteriaValue;
|
|
} else if (clazz.isAssignableFrom(LocalDateTime.class)) {
|
return dateTimeValue(criteriaValue.toString(), criterion.isEndOfTheDay());
|
|
} else {
|
return clazz.cast(criteriaValue);
|
}
|
}
|
|
private Object dateTimeValue(String criteriaValue, boolean endOfTheDay) {
|
ZonedDateTime zonedDateTime = ZonedDateTime.parse(criteriaValue, DateTimeFormatter.ISO_DATE_TIME);
|
LocalDateTime date = Timestamp.from(zonedDateTime.toInstant()).toLocalDateTime();
|
|
return endOfTheDay
|
? date.toLocalDate().atTime(LocalTime.MAX)
|
: date.toLocalDate().atTime(LocalTime.MIN);
|
}
|
|
private boolean isUnaryOperator(Operateur operateur) {
|
return operateur.equals(Operateur.IS_NOT_NULL) || operateur.equals(Operateur.IS_NULL);
|
}
|
}
|