Soft Module metadata as complex map value (#2568)
--------- Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -149,17 +149,16 @@ public class SpecificationBuilder<T> {
|
||||
if (comparison.getValue() == null) {
|
||||
// map entry with key is null (doesn't exist) / is not null (exists) - use left join with on
|
||||
return switch (op) {
|
||||
case EQ -> cb.isNull(pathResolver.getJoinOn(attribute, split[1]));
|
||||
case NE -> cb.isNotNull(pathResolver.getJoinOn(attribute, split[1]));
|
||||
case EQ -> cb.isNull(toMapValuePath(pathResolver.getJoinOn(attribute, split[1])));
|
||||
case NE -> cb.isNotNull(toMapValuePath(pathResolver.getJoinOn(attribute, split[1])));
|
||||
default -> throw new RSQLParameterSyntaxException(
|
||||
String.format("Operator %s is not supported for map fields with value null", op));
|
||||
};
|
||||
} else {
|
||||
final MapJoin<?, ?, ?> mapPath = (MapJoin<?, ?, ?>) pathResolver.getPath(attribute);
|
||||
final Path<String> valuePath = (Path<String>) mapPath.value();
|
||||
return isNot(op)
|
||||
? compare(comparison, pathResolver.getJoinOnInner(attribute, split[1]))
|
||||
: cb.and(equal(mapPath.key(), split[1]), compare(comparison, valuePath));
|
||||
? compare(comparison, toMapValuePath(pathResolver.getJoinOnInner(attribute, split[1])))
|
||||
: cb.and(equal(mapPath.key(), split[1]), compare(comparison, toMapValuePath(mapPath)));
|
||||
}
|
||||
} else if (attribute instanceof SetAttribute<?, ?> setAttribute) {
|
||||
if (split.length < 2 || ObjectUtils.isEmpty(split[1])) {
|
||||
@@ -185,6 +184,12 @@ public class SpecificationBuilder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Path<String> toMapValuePath(final Path<?> mapJoin) {
|
||||
final Path<?> valuePath = ((MapJoin<?, ?, ?>) mapJoin).value();
|
||||
return valuePath.getJavaType() == String.class ? (Path<String>) valuePath : valuePath.get("value");
|
||||
}
|
||||
|
||||
private Predicate compare(final Comparison comparison, final Path<?> fieldPath) {
|
||||
final List<Object> values = getValues(comparison, fieldPath.getJavaType());
|
||||
final Object firstValue = values.get(0);
|
||||
|
||||
@@ -343,8 +343,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & RsqlQueryField, T> extends
|
||||
|
||||
final Predicate mapPredicate = mapToMapPredicate(fieldPath, queryPath);
|
||||
|
||||
|
||||
final Predicate valuePredicate = addOperatorPredicate(node, fieldPath, transformedValues, value, queryPath);
|
||||
final Predicate valuePredicate = addOperatorPredicate(node, queryPath.getEnumValue().isMap() ? (Path)toMapValuePath(fieldPath) : fieldPath, transformedValues, value, queryPath);
|
||||
return toSingleList(mapPredicate != null ? cb.and(mapPredicate, valuePredicate) : valuePredicate);
|
||||
}
|
||||
|
||||
@@ -380,6 +379,16 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & RsqlQueryField, T> extends
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Path<String> toMapValuePath(final Path<?> fieldPath) {
|
||||
final Path<?> mapValuePath = ((MapJoin<?, ?, ?>) pathOfString(fieldPath)).value();
|
||||
if (mapValuePath.getJavaType() == String.class) {
|
||||
return (Path<String>) mapValuePath;
|
||||
} else {
|
||||
return mapValuePath.get("value");
|
||||
}
|
||||
}
|
||||
|
||||
private Predicate getOutPredicate(
|
||||
final List<Object> transformedValues,
|
||||
final QueryPath queryPath, final Path<Object> fieldPath) {
|
||||
@@ -496,8 +505,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & RsqlQueryField, T> extends
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Expression<String> getExpressionToCompare(final Path innerFieldPath, final A enumField) {
|
||||
if (enumField.isMap()){
|
||||
// Currently we support only string key. So below cast is safe.
|
||||
return (Expression<String>) (((MapJoin<?, ?, ?>) pathOfString(innerFieldPath)).value());
|
||||
return toMapValuePath(innerFieldPath);
|
||||
} else {
|
||||
return pathOfString(innerFieldPath);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & RsqlQueryField, T>
|
||||
if (values.get(0) == null) {
|
||||
// IS operator for maps and null value is treated as doesn't exist correspondingly
|
||||
((PluralJoin<?, ?, ?>) fieldPath).on(toMapEntryKeyPredicate(queryPath, fieldPath));
|
||||
return cb.isNull(fieldPath);
|
||||
return cb.isNull(toMapValuePath(fieldPath));
|
||||
}
|
||||
} else if (node.getOperator() == NOT) {
|
||||
if (values.size() != 1) {
|
||||
@@ -139,10 +139,10 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & RsqlQueryField, T>
|
||||
((PluralJoin<?, ?, ?>) fieldPath).on(toMapEntryKeyPredicate(queryPath, fieldPath));
|
||||
if (values.get(0) == null) {
|
||||
// special handling of "exists"
|
||||
return cb.isNotNull(fieldPath);
|
||||
return cb.isNotNull(toMapValuePath(fieldPath));
|
||||
} else {
|
||||
// special handling or "not equal" or null (same as != but with possible optimized join - no subquery)
|
||||
return toNotEqualToPredicate(queryPath, fieldPath, values.get(0));
|
||||
return toNotEqualToPredicate(queryPath, toMapValuePath(fieldPath), values.get(0));
|
||||
}
|
||||
}
|
||||
mapEntryKeyPredicate = toMapEntryKeyPredicate(queryPath, fieldPath);
|
||||
@@ -150,11 +150,21 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & RsqlQueryField, T>
|
||||
mapEntryKeyPredicate = null;
|
||||
}
|
||||
|
||||
final Predicate valuePredicate = toOperatorAndValuePredicate(node, queryPath, fieldPath, values);
|
||||
final Predicate valuePredicate = toOperatorAndValuePredicate(node, queryPath, queryPath.getEnumValue().isMap() ? toMapValuePath(fieldPath) : fieldPath, values);
|
||||
|
||||
return mapEntryKeyPredicate == null ? valuePredicate : cb.and(mapEntryKeyPredicate, valuePredicate);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Path<String> toMapValuePath(final Path<?> fieldPath) {
|
||||
final Path<?> mapValuePath = ((MapJoin<?, ?, ?>) pathOfString(fieldPath)).value();
|
||||
if (mapValuePath.getJavaType() == String.class) {
|
||||
return (Path<String>) mapValuePath;
|
||||
} else {
|
||||
return mapValuePath.get("value");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Predicate toMapEntryKeyPredicate(final QueryPath queryPath, final Path<?> fieldPath) {
|
||||
final String[] graph = queryPath.getJpaPath();
|
||||
@@ -341,7 +351,7 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & RsqlQueryField, T>
|
||||
private Path<String> getExpressionToCompare(final A enumField, final Path fieldPath) {
|
||||
if (enumField.isMap()) {
|
||||
// Currently we support only string key. So below cast is safe.
|
||||
return (Path<String>) (((MapJoin<?, ?, ?>) fieldPath).value());
|
||||
return toMapValuePath(fieldPath);
|
||||
} else {
|
||||
return pathOfString(fieldPath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user