diff --git a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/CriterionOperator.java b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/CriterionOperator.java index dade63f31cba2fc9325e570f4a7ddedf2951aee8..0afca9835701b02059958c51838bf245f6fcd81c 100644 --- a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/CriterionOperator.java +++ b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/CriterionOperator.java @@ -49,5 +49,6 @@ public enum CriterionOperator { CONTAINS, CONTAINSIGNORECASE, BETWEEN, - STARTWITH; + STARTWITH, + ELEMMATCH } diff --git a/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java b/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java index 4b6f344e437bfc1574c2b409d436444b83b269ac..740963ba893f204ff40a93d640ed52253231e69f 100644 --- a/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java +++ b/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java @@ -39,6 +39,7 @@ package fr.gouv.vitamui.commons.mongo.utils; import java.lang.reflect.Type; import java.time.Duration; import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -46,6 +47,9 @@ import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; +import fr.gouv.vitamui.commons.api.domain.QueryDto; +import fr.gouv.vitamui.commons.api.domain.QueryOperator; +import fr.gouv.vitamui.commons.utils.JsonUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.CriteriaDefinition; @@ -185,6 +189,8 @@ public final class MongoUtils { mapValue.put(BETWEEN_OPERATOR_KEY_START, convertValue(parametrizedClazz, mapValue.get(BETWEEN_OPERATOR_KEY_START))); mapValue.put(BETWEEN_OPEARTOR_KEY_END, convertValue(parametrizedClazz, mapValue.get(BETWEEN_OPEARTOR_KEY_END))); return mapValue; + case ELEMMATCH: + return convertValue(QueryDto.class, value); default : return convertValue(parametrizedClazz, value); } @@ -209,6 +215,14 @@ public final class MongoUtils { return Boolean.parseBoolean(value.toString()); } else if (VitamUIUtils.canBeCastByClass(value, List.class)) { return value; + } else if (clazz.equals(QueryDto.class)) { + try { + // we convert the linked hash map to json to re-convert it properly to query dto + return QueryDto.fromJson(JsonUtils.toJson(value)); + } + catch (Exception e) { + throw new InvalidFormatException(e.getMessage(), e); + } } return CastUtils.castValue(value, clazz); @@ -275,12 +289,36 @@ public final class MongoUtils { final Criteria endCriteria = Criteria.where(key).lte(mapVal.get(BETWEEN_OPEARTOR_KEY_END)); criteria = buildAndOperator(startCriteria, endCriteria); break; + case ELEMMATCH : + criteria = Criteria.where(key).elemMatch(queryDTOToCriterion((QueryDto)val)); + break; default : throw new IllegalArgumentException("Operator " + operator + " is not supported"); } return criteria; } + public static Criteria queryDTOToCriterion(QueryDto queryDto) { + Collection<CriteriaDefinition> criteria = new ArrayList<>(); + queryDto.getCriterionList().forEach(criterion -> { + criteria.add(MongoUtils.getCriteria(criterion.getKey(), criterion.getValue(), criterion.getOperator())); + }); + + // if the criteria contains subQueries, a recursive call is made for each subQuery + queryDto.getSubQueries().forEach(queryDtoItem -> { + criteria.add(queryDTOToCriterion(queryDtoItem)); + }); + + final Criteria commonCustomCriteria = new Criteria(); + if (queryDto.getQueryOperator() == QueryOperator.AND) { + commonCustomCriteria.andOperator(criteria.stream().map(c -> (Criteria) c).toArray(Criteria[]::new)); + } else if (queryDto.getQueryOperator() == QueryOperator.OR) { + commonCustomCriteria.orOperator(criteria.stream().map(c -> (Criteria) c).toArray(Criteria[]::new)); + } + return commonCustomCriteria; + } + + public static Type getTypeOfField(final Class<?> entityClass, final String fieldName) { try { return ReflectionUtils.getTypeOfField(entityClass, fieldName);