Refactor RSQL Utility - make it singleton and injectable (#2536)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -19,13 +19,10 @@ import jakarta.persistence.criteria.CriteriaQuery;
|
||||
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder;
|
||||
|
||||
public class HawkbitQlToSql {
|
||||
|
||||
private static final Database DATABASE = Database.H2;
|
||||
private final EntityManager entityManager;
|
||||
private final boolean isEclipselink;
|
||||
|
||||
@@ -61,16 +58,16 @@ public class HawkbitQlToSql {
|
||||
final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final RsqlToSpecBuilder rsqlToSpecBuilder) {
|
||||
final CriteriaQuery<T> query = entityManager.getCriteriaBuilder().createQuery(domainClass);
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final RsqlToSpecBuilder defaultRsqlToSpecBuilder = RsqlConfigHolder.getInstance().getRsqlToSpecBuilder();
|
||||
final RsqlToSpecBuilder defaultRsqlToSpecBuilder = RsqlUtility.getInstance().getRsqlToSpecBuilder();
|
||||
if (defaultRsqlToSpecBuilder != rsqlToSpecBuilder) {
|
||||
RsqlConfigHolder.getInstance().setRsqlToSpecBuilder(rsqlToSpecBuilder);
|
||||
RsqlUtility.getInstance().setRsqlToSpecBuilder(rsqlToSpecBuilder);
|
||||
}
|
||||
try {
|
||||
return query.where(RsqlUtility.<A, T> buildRsqlSpecification(rsql, fieldsClass, null, DATABASE)
|
||||
return query.where(RsqlUtility.getInstance().<A, T> buildRsqlSpecification(rsql, fieldsClass)
|
||||
.toPredicate(query.from(domainClass), cb.createQuery(domainClass), cb));
|
||||
} finally {
|
||||
if (defaultRsqlToSpecBuilder != rsqlToSpecBuilder) {
|
||||
RsqlConfigHolder.getInstance().setRsqlToSpecBuilder(defaultRsqlToSpecBuilder);
|
||||
RsqlUtility.getInstance().setRsqlToSpecBuilder(defaultRsqlToSpecBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
/**
|
||||
* Helper class providing static access to the RSQL configuration as managed bean.
|
||||
*/
|
||||
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
|
||||
@Getter
|
||||
@SuppressWarnings("java:S6548") // singleton holder ensures static access to spring resources in some places
|
||||
public final class RsqlConfigHolder {
|
||||
|
||||
private static final RsqlConfigHolder SINGLETON = new RsqlConfigHolder();
|
||||
|
||||
public enum RsqlToSpecBuilder {
|
||||
LEGACY_G1, // legacy RSQL visitor
|
||||
LEGACY_G2, // G2 RSQL visitor
|
||||
G3 // G3 RSQL visitor - still experimental / yet default
|
||||
}
|
||||
/**
|
||||
* If RSQL comparison operators shall ignore the case. If ignore case is <code>true</code> "x == ax" will match "x == aX"
|
||||
*/
|
||||
@Value("${hawkbit.rsql.ignore-case:true}")
|
||||
private boolean ignoreCase;
|
||||
/**
|
||||
* Declares if the database is case-insensitive, by default assumes <code>false</code>. In case it is case-sensitive and,
|
||||
* {@link #ignoreCase} is set to <code>true</code> the SQL queries use upper case comparisons to ignore case.
|
||||
*
|
||||
* If the database is declared as case-sensitive and ignoreCase is set to <code>false</code> the RSQL queries shall use strict
|
||||
* syntax - i.e. 'and' instead of 'AND' / 'aND'. Otherwise, the queries would be case-insensitive regarding operators.
|
||||
*/
|
||||
@Value("${hawkbit.rsql.case-insensitive-db:false}")
|
||||
private boolean caseInsensitiveDB;
|
||||
|
||||
/**
|
||||
* @deprecated in favour fixed final visitor / spec builder of G2 RSQL visitor / G3 spec builder. since 0.6.0
|
||||
*/
|
||||
@Setter // for tests only
|
||||
@Deprecated(forRemoval = true, since = "0.6.0")
|
||||
@Value("${hawkbit.rsql.rsql-to-spec-builder:G3}") //
|
||||
private RsqlToSpecBuilder rsqlToSpecBuilder;
|
||||
|
||||
/**
|
||||
* @return The holder singleton instance.
|
||||
*/
|
||||
public static RsqlConfigHolder getInstance() {
|
||||
return SINGLETON;
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,15 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.G3;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
|
||||
import cz.jirutka.rsql.parser.RSQLParserException;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.text.StrLookup;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
@@ -27,6 +27,9 @@ import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.legacy.SpecificationBuilderLegacy;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
|
||||
@@ -64,8 +67,66 @@ import org.springframework.orm.jpa.vendor.Database;
|
||||
* $${OVERDUE_TS} would prevent the ${OVERDUE_TS} token from being expanded.
|
||||
*/
|
||||
@Slf4j
|
||||
@Getter
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class RsqlUtility {
|
||||
public class RsqlUtility {
|
||||
|
||||
private static final RsqlUtility SINGLETON = new RsqlUtility();
|
||||
|
||||
public enum RsqlToSpecBuilder {
|
||||
LEGACY_G1, // legacy RSQL visitor
|
||||
LEGACY_G2, // G2 RSQL visitor
|
||||
G3 // G3 RSQL visitor - still experimental / yet default
|
||||
}
|
||||
|
||||
/**
|
||||
* If RSQL comparison operators shall ignore the case. If ignore case is <code>true</code> "x == ax" will match "x == aX"
|
||||
*/
|
||||
@Value("${hawkbit.rsql.ignore-case:true}")
|
||||
private boolean ignoreCase;
|
||||
/**
|
||||
* Declares if the database is case-insensitive, by default assumes <code>false</code>. In case it is case-sensitive and,
|
||||
* {@link #ignoreCase} is set to <code>true</code> the SQL queries use upper case comparisons to ignore case.
|
||||
* <p/>
|
||||
* If the database is declared as case-sensitive and ignoreCase is set to <code>false</code> the RSQL queries shall use strict
|
||||
* syntax - i.e. 'and' instead of 'AND' / 'aND'. Otherwise, the queries would be case-insensitive regarding operators.
|
||||
*/
|
||||
@Value("${hawkbit.rsql.case-insensitive-db:false}")
|
||||
private boolean caseInsensitiveDB;
|
||||
|
||||
/**
|
||||
* @deprecated in favour fixed final visitor / spec builder of G2 RSQL visitor / G3 spec builder. since 0.6.0
|
||||
*/
|
||||
@Setter // for tests only
|
||||
@Deprecated(forRemoval = true, since = "0.6.0")
|
||||
@Value("${hawkbit.rsql.rsql-to-spec-builder:G3}") //
|
||||
private RsqlToSpecBuilder rsqlToSpecBuilder;
|
||||
|
||||
private VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private Database database;
|
||||
private EntityManager entityManager;
|
||||
|
||||
/**
|
||||
* @return The holder singleton instance.
|
||||
*/
|
||||
public static RsqlUtility getInstance() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setVirtualPropertyReplacer(final VirtualPropertyReplacer virtualPropertyReplacer) {
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
void setDatabase(final JpaProperties jpaProperties) {
|
||||
database = jpaProperties.getDatabase();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
void setEntityManager(final EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a JPA {@link Specification} which corresponds with the given RSQL query. The specification can be used to filter for JPA entities
|
||||
@@ -73,25 +134,16 @@ public final class RsqlUtility {
|
||||
*
|
||||
* @param rsql the rsql query to be parsed
|
||||
* @param rsqlQueryFieldType the enum class type which implements the {@link RsqlQueryField}
|
||||
* @param virtualPropertyReplacer holds the logic how the known macros have to be resolved; may be <code>null</code>
|
||||
* @param database database in use
|
||||
* @return a specification which can be used with JPA
|
||||
* @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
||||
*/
|
||||
public static <A extends Enum<A> & RsqlQueryField, T> Specification<T> buildRsqlSpecification(
|
||||
final String rsql, final Class<A> rsqlQueryFieldType,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) {
|
||||
if (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == G3) {
|
||||
return new SpecificationBuilder<T>(
|
||||
virtualPropertyReplacer,
|
||||
!RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance().isIgnoreCase(),
|
||||
database)
|
||||
.specification(RsqlParser.parse(
|
||||
RsqlConfigHolder.getInstance().isCaseInsensitiveDB() || RsqlConfigHolder.getInstance().isIgnoreCase()
|
||||
? rsql.toLowerCase() : rsql,
|
||||
rsqlQueryFieldType));
|
||||
public <A extends Enum<A> & RsqlQueryField, T> Specification<T> buildRsqlSpecification(
|
||||
final String rsql, final Class<A> rsqlQueryFieldType) {
|
||||
if (rsqlToSpecBuilder == RsqlToSpecBuilder.G3) {
|
||||
return new SpecificationBuilder<T>(virtualPropertyReplacer, !caseInsensitiveDB && ignoreCase, database)
|
||||
.specification(RsqlParser.parse(caseInsensitiveDB || ignoreCase ? rsql.toLowerCase() : rsql, rsqlQueryFieldType));
|
||||
} else {
|
||||
return new SpecificationBuilderLegacy<A, T>(rsqlQueryFieldType, virtualPropertyReplacer, database).specification(rsql);
|
||||
}
|
||||
@@ -101,18 +153,16 @@ public final class RsqlUtility {
|
||||
* Validates the RSQL string
|
||||
*
|
||||
* @param rsql RSQL string to validate
|
||||
* @param rsqlQueryFieldType
|
||||
* @param rsqlQueryFieldType the enum class type which implements the {@link RsqlQueryField}
|
||||
* @param jpaType the JPA entity type to validate against
|
||||
* @throws RSQLParserException if RSQL syntax is invalid
|
||||
* @throws RSQLParameterUnsupportedFieldException if RSQL key is not allowed
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static <A extends Enum<A> & RsqlQueryField> void validateRsqlFor(
|
||||
final String rsql, final Class<A> rsqlQueryFieldType,
|
||||
final Class<?> jpaType,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final EntityManager entityManager) {
|
||||
public <A extends Enum<A> & RsqlQueryField> void validateRsqlFor(
|
||||
final String rsql, final Class<A> rsqlQueryFieldType, final Class<?> jpaType) {
|
||||
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<?> criteriaQuery = criteriaBuilder.createQuery(jpaType);
|
||||
buildRsqlSpecification(rsql, rsqlQueryFieldType, virtualPropertyReplacer, null)
|
||||
.toPredicate(criteriaQuery.from((Class) jpaType), criteriaQuery, criteriaBuilder);
|
||||
buildRsqlSpecification(rsql, rsqlQueryFieldType).toPredicate(criteriaQuery.from((Class) jpaType), criteriaQuery, criteriaBuilder);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.legacy;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.legacy.AbstractRSQLVisitor.OPERATORS;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
@@ -50,14 +50,14 @@ public class SpecificationBuilderLegacy<A extends Enum<A> & RsqlQueryField, T> {
|
||||
|
||||
public Specification<T> specification(final String rsql) {
|
||||
return (root, query, cb) -> {
|
||||
final RsqlConfigHolder rsqlConfigHolder = RsqlConfigHolder.getInstance();
|
||||
final RsqlUtility rsqlUtility = RsqlUtility.getInstance();
|
||||
|
||||
final Node rootNode = parseRsql(rsql, rsqlConfigHolder);
|
||||
final Node rootNode = parseRsql(rsql, rsqlUtility);
|
||||
query.distinct(true);
|
||||
|
||||
final boolean ensureIgnoreCase = !rsqlConfigHolder.isCaseInsensitiveDB() && rsqlConfigHolder.isIgnoreCase();
|
||||
final boolean ensureIgnoreCase = !rsqlUtility.isCaseInsensitiveDB() && rsqlUtility.isIgnoreCase();
|
||||
final RSQLVisitor<List<Predicate>, String> jpqQueryRSQLVisitor =
|
||||
rsqlConfigHolder.getRsqlToSpecBuilder() == LEGACY_G1
|
||||
rsqlUtility.getRsqlToSpecBuilder() == LEGACY_G1
|
||||
? new JpaQueryRsqlVisitor<>(root, cb, rsqlQueryFieldType, virtualPropertyReplacer, database, query, ensureIgnoreCase)
|
||||
: new JpaQueryRsqlVisitorG2<>(rsqlQueryFieldType, root, query, cb, database, virtualPropertyReplacer, ensureIgnoreCase);
|
||||
final List<Predicate> accept = rootNode.accept(jpqQueryRSQLVisitor);
|
||||
@@ -70,10 +70,10 @@ public class SpecificationBuilderLegacy<A extends Enum<A> & RsqlQueryField, T> {
|
||||
};
|
||||
}
|
||||
|
||||
private static Node parseRsql(final String rsql, final RsqlConfigHolder rsqlConfigHolder) {
|
||||
private static Node parseRsql(final String rsql, final RsqlUtility rsqlUtility) {
|
||||
log.debug("Parsing rsql string {}", rsql);
|
||||
try {
|
||||
return new RSQLParser(OPERATORS).parse(rsqlConfigHolder.isCaseInsensitiveDB() || rsqlConfigHolder.isIgnoreCase() ? rsql.toLowerCase() : rsql);
|
||||
return new RSQLParser(OPERATORS).parse(rsqlUtility.isCaseInsensitiveDB() || rsqlUtility.isIgnoreCase() ? rsql.toLowerCase() : rsql);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw new RSQLParameterSyntaxException("RSQL filter must not be null", e);
|
||||
} catch (final RSQLParserException e) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
@@ -7,10 +7,10 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G2;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G2;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -18,9 +18,9 @@ import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.legacy.SpecificationBuilderLegacy;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
@@ -32,12 +32,12 @@ class SpecificationBuilderLegacyTest extends SpecificationBuilderTest {
|
||||
private final SpecificationBuilderLegacy<RootField, Root> builder = new SpecificationBuilderLegacy<>(RootField.class, null, Database.H2);
|
||||
|
||||
private static void runWithRsqlToSpecBuilder(final Runnable runnable, final RsqlToSpecBuilder rsqlToSpecBuilder) {
|
||||
final RsqlToSpecBuilder defaultBuilder = RsqlConfigHolder.getInstance().getRsqlToSpecBuilder();
|
||||
RsqlConfigHolder.getInstance().setRsqlToSpecBuilder(rsqlToSpecBuilder);
|
||||
final RsqlToSpecBuilder defaultBuilder = RsqlUtility.getInstance().getRsqlToSpecBuilder();
|
||||
RsqlUtility.getInstance().setRsqlToSpecBuilder(rsqlToSpecBuilder);
|
||||
try {
|
||||
runnable.run();
|
||||
} finally {
|
||||
RsqlConfigHolder.getInstance().setRsqlToSpecBuilder(defaultBuilder);
|
||||
RsqlUtility.getInstance().setRsqlToSpecBuilder(defaultBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.G3;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G2;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.G3;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G2;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -22,11 +22,9 @@ import java.util.stream.StreamSupport;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.jpa.ql.EntityMatcher;
|
||||
import org.eclipse.hawkbit.repository.jpa.ql.utils.HawkbitQlToSql;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser;
|
||||
import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
@@ -491,8 +489,8 @@ class SpecificationBuilderTest {
|
||||
return builder.specification(RsqlParser.parse(rsql));
|
||||
}
|
||||
|
||||
private static RsqlConfigHolder.RsqlToSpecBuilder getRsqlToSpecBuilder() {
|
||||
return RsqlConfigHolder.getInstance().getRsqlToSpecBuilder();
|
||||
private static RsqlUtility.RsqlToSpecBuilder getRsqlToSpecBuilder() {
|
||||
return RsqlUtility.getInstance().getRsqlToSpecBuilder();
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@@ -7,16 +7,13 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql.sa;
|
||||
package org.eclipse.hawkbit.repository.jpa.ql;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
@@ -154,7 +154,7 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
|
||||
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||
@@ -538,15 +538,13 @@ public class RepositoryApplicationConfiguration {
|
||||
final TargetRepository targetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final SoftwareModuleRepository softwareModuleRepository,
|
||||
final DistributionSetTagRepository distributionSetTagRepository,
|
||||
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final DistributionSetTagRepository distributionSetTagRepository, final RepositoryProperties repositoryProperties) {
|
||||
return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement,
|
||||
systemManagement, distributionSetTypeManagement, quotaManagement,
|
||||
targetRepository, targetFilterQueryRepository, actionRepository,
|
||||
TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement),
|
||||
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository,
|
||||
properties.getDatabase(), repositoryProperties);
|
||||
softwareModuleRepository, distributionSetTagRepository, repositoryProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,11 +558,9 @@ public class RepositoryApplicationConfiguration {
|
||||
final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
|
||||
final DistributionSetRepository distributionSetRepository, final TargetTypeRepository targetTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties,
|
||||
final QuotaManagement quotaManagement) {
|
||||
return new JpaDistributionSetTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository,
|
||||
distributionSetRepository, targetTypeRepository, virtualPropertyReplacer, properties.getDatabase(),
|
||||
quotaManagement);
|
||||
distributionSetRepository, targetTypeRepository, quotaManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,10 +572,8 @@ public class RepositoryApplicationConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
TargetTypeManagement targetTypeManagement(final TargetTypeRepository targetTypeRepository,
|
||||
final TargetRepository targetRepository, final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties,
|
||||
final QuotaManagement quotaManagement) {
|
||||
return new JpaTargetTypeManagement(targetTypeRepository, targetRepository, distributionSetTypeRepository,
|
||||
virtualPropertyReplacer, properties.getDatabase(), quotaManagement);
|
||||
return new JpaTargetTypeManagement(targetTypeRepository, targetRepository, distributionSetTypeRepository, quotaManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -618,18 +612,16 @@ public class RepositoryApplicationConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
TargetManagement targetManagement(final EntityManager entityManager, final QuotaManagement quotaManagement,
|
||||
TargetManagement targetManagement(
|
||||
final EntityManager entityManager, final QuotaManagement quotaManagement,
|
||||
final TargetRepository targetRepository,
|
||||
final RolloutGroupRepository rolloutGroupRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository,
|
||||
final TenantAware tenantAware,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final JpaProperties properties, final DistributionSetManagement distributionSetManagement) {
|
||||
final TenantAware tenantAware, final DistributionSetManagement distributionSetManagement) {
|
||||
return new JpaTargetManagement(entityManager, distributionSetManagement, quotaManagement, targetRepository,
|
||||
targetTypeRepository, rolloutGroupRepository, targetFilterQueryRepository,
|
||||
targetTagRepository, tenantAware, virtualPropertyReplacer,
|
||||
properties.getDatabase());
|
||||
targetTagRepository, tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -637,25 +629,20 @@ public class RepositoryApplicationConfiguration {
|
||||
*
|
||||
* @param targetFilterQueryRepository holding {@link TargetFilterQuery} entities
|
||||
* @param targetManagement managing {@link Target} entities
|
||||
* @param virtualPropertyReplacer for RSQL handling
|
||||
* @param distributionSetManagement for auto assign DS access
|
||||
* @param quotaManagement to access quotas
|
||||
* @param properties JPA properties
|
||||
* @return a new {@link TargetFilterQueryManagement}
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
TargetFilterQueryManagement targetFilterQueryManagement(
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final TargetManagement targetManagement,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||
final JpaProperties properties, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final RepositoryProperties repositoryProperties,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware,
|
||||
final EntityManager entityManager) {
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final RepositoryProperties repositoryProperties,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) {
|
||||
return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, targetManagement,
|
||||
virtualPropertyReplacer, distributionSetManagement, quotaManagement, properties.getDatabase(),
|
||||
tenantConfigurationManagement, repositoryProperties, systemSecurityContext, contextAware, auditorAware, entityManager);
|
||||
distributionSetManagement, quotaManagement, tenantConfigurationManagement, repositoryProperties,
|
||||
systemSecurityContext, contextAware, auditorAware);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,11 +652,8 @@ public class RepositoryApplicationConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
TargetTagManagement targetTagManagement(final TargetTagRepository targetTagRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final JpaProperties properties) {
|
||||
return new JpaTargetTagManagement(targetTagRepository, virtualPropertyReplacer,
|
||||
properties.getDatabase());
|
||||
TargetTagManagement targetTagManagement(final TargetTagRepository targetTagRepository) {
|
||||
return new JpaTargetTagManagement(targetTagRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -681,10 +665,9 @@ public class RepositoryApplicationConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
DistributionSetTagManagement distributionSetTagManagement(
|
||||
final DistributionSetTagRepository distributionSetTagRepository,
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties) {
|
||||
final DistributionSetRepository distributionSetRepository) {
|
||||
return new JpaDistributionSetTagManagement(
|
||||
distributionSetTagRepository, distributionSetRepository, virtualPropertyReplacer, properties.getDatabase());
|
||||
distributionSetTagRepository, distributionSetRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,13 +682,9 @@ public class RepositoryApplicationConfiguration {
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final SoftwareModuleMetadataRepository softwareModuleMetadataRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository, final AuditorAware<String> auditorProvider,
|
||||
final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final JpaProperties properties) {
|
||||
final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement) {
|
||||
return new JpaSoftwareModuleManagement(entityManager, distributionSetRepository, softwareModuleRepository,
|
||||
softwareModuleMetadataRepository, softwareModuleTypeRepository, auditorProvider, artifactManagement,
|
||||
quotaManagement, virtualPropertyReplacer,
|
||||
properties.getDatabase());
|
||||
softwareModuleMetadataRepository, softwareModuleTypeRepository, auditorProvider, artifactManagement, quotaManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -718,11 +697,8 @@ public class RepositoryApplicationConfiguration {
|
||||
SoftwareModuleTypeManagement softwareModuleTypeManagement(
|
||||
final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final JpaProperties properties) {
|
||||
return new JpaSoftwareModuleTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository,
|
||||
virtualPropertyReplacer, softwareModuleRepository, properties.getDatabase());
|
||||
final SoftwareModuleRepository softwareModuleRepository) {
|
||||
return new JpaSoftwareModuleTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository, softwareModuleRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -765,14 +741,12 @@ public class RepositoryApplicationConfiguration {
|
||||
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final QuotaManagement quotaManagement,
|
||||
final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final JpaProperties properties,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware,
|
||||
final RepositoryProperties repositoryProperties) {
|
||||
return new JpaRolloutManagement(rolloutRepository, rolloutGroupRepository, rolloutApprovalStrategy,
|
||||
startNextRolloutGroupAction, rolloutStatusCache, actionRepository, targetManagement,
|
||||
distributionSetManagement, tenantConfigurationManagement, quotaManagement, afterCommit,
|
||||
virtualPropertyReplacer, systemSecurityContext, contextAware, properties.getDatabase(),
|
||||
repositoryProperties);
|
||||
systemSecurityContext, contextAware, repositoryProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -798,11 +772,9 @@ public class RepositoryApplicationConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
RolloutGroupManagement rolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository,
|
||||
final RolloutRepository rolloutRepository, final ActionRepository actionRepository,
|
||||
final TargetRepository targetRepository, final EntityManager entityManager,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache,
|
||||
final JpaProperties properties) {
|
||||
final TargetRepository targetRepository, final EntityManager entityManager, final RolloutStatusCache rolloutStatusCache) {
|
||||
return new JpaRolloutGroupManagement(rolloutGroupRepository, rolloutRepository, actionRepository,
|
||||
targetRepository, entityManager, virtualPropertyReplacer, rolloutStatusCache, properties.getDatabase());
|
||||
targetRepository, entityManager, rolloutStatusCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -816,14 +788,13 @@ public class RepositoryApplicationConfiguration {
|
||||
final ActionRepository actionRepository,
|
||||
final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository,
|
||||
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
|
||||
final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||
final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware<String> auditorAware,
|
||||
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetManagement, targetRepository, actionStatusRepository,
|
||||
auditorProvider,
|
||||
afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement,
|
||||
afterCommit, txManager, tenantConfigurationManagement,
|
||||
quotaManagement, systemSecurityContext, tenantAware, auditorAware, properties.getDatabase(), repositoryProperties);
|
||||
}
|
||||
|
||||
@@ -1010,13 +981,13 @@ public class RepositoryApplicationConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the {@link RsqlConfigHolder} bean.
|
||||
* Register the {@link RsqlUtility} bean to force Spring to inject values and auto-wired fields.
|
||||
*
|
||||
* @return The {@link RsqlConfigHolder} singleton.
|
||||
* @return The {@link RsqlUtility} singleton.
|
||||
*/
|
||||
@Bean
|
||||
RsqlConfigHolder rsqlConfigHolder() {
|
||||
return RsqlConfigHolder.getInstance();
|
||||
RsqlUtility rsqlUtility() {
|
||||
return RsqlUtility.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,7 +86,6 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
||||
@@ -150,7 +149,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final TargetRepository targetRepository;
|
||||
private final AuditorAware<String> auditorProvider;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final PlatformTransactionManager txManager;
|
||||
private final OnlineDsAssignmentStrategy onlineDsAssignmentStrategy;
|
||||
private final OfflineDsAssignmentStrategy offlineDsAssignmentStrategy;
|
||||
@@ -166,8 +164,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
final EntityManager entityManager, final ActionRepository actionRepository,
|
||||
final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository,
|
||||
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
|
||||
final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||
final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware<String> auditorAware,
|
||||
final Database database, final RepositoryProperties repositoryProperties) {
|
||||
@@ -176,7 +173,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.targetRepository = targetRepository;
|
||||
this.auditorProvider = auditorProvider;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.txManager = txManager;
|
||||
onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit,
|
||||
actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled,
|
||||
@@ -274,7 +270,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
assertTargetReadAllowed(controllerId);
|
||||
|
||||
final List<Specification<JpaAction>> specList = Arrays.asList(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, ActionFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class),
|
||||
ActionSpecifications.byTargetControllerId(controllerId));
|
||||
|
||||
return JpaManagementHelper.countBySpec(actionRepository, specList);
|
||||
@@ -287,8 +283,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
|
||||
@Override
|
||||
public long countActions(final String rsql) {
|
||||
final List<Specification<JpaAction>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, ActionFields.class, virtualPropertyReplacer, database));
|
||||
final List<Specification<JpaAction>> specList = List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class));
|
||||
return JpaManagementHelper.countBySpec(actionRepository, specList);
|
||||
}
|
||||
|
||||
@@ -312,8 +307,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
|
||||
@Override
|
||||
public Slice<Action> findActions(final String rsql, final Pageable pageable) {
|
||||
final List<Specification<JpaAction>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, ActionFields.class, virtualPropertyReplacer, database));
|
||||
final List<Specification<JpaAction>> specList = List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class));
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@@ -322,7 +316,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
assertTargetReadAllowed(controllerId);
|
||||
|
||||
final List<Specification<JpaAction>> specList = Arrays.asList(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, ActionFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class),
|
||||
ActionSpecifications.byTargetControllerId(controllerId));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(actionRepository, specList, pageable);
|
||||
|
||||
@@ -73,14 +73,12 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Statistic;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -105,10 +103,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final ActionRepository actionRepository;
|
||||
private final TenantConfigHelper tenantConfigHelper;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final SoftwareModuleRepository softwareModuleRepository;
|
||||
private final DistributionSetTagRepository distributionSetTagRepository;
|
||||
private final Database database;
|
||||
private final RepositoryProperties repositoryProperties;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
@@ -120,10 +116,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
final TargetRepository targetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||
final TenantConfigHelper tenantConfigHelper,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final DistributionSetTagRepository distributionSetTagRepository,
|
||||
final Database database,
|
||||
final RepositoryProperties repositoryProperties) {
|
||||
this.entityManager = entityManager;
|
||||
this.distributionSetRepository = distributionSetRepository;
|
||||
@@ -135,10 +129,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||
this.actionRepository = actionRepository;
|
||||
this.tenantConfigHelper = tenantConfigHelper;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.softwareModuleRepository = softwareModuleRepository;
|
||||
this.distributionSetTagRepository = distributionSetTagRepository;
|
||||
this.database = database;
|
||||
this.repositoryProperties = repositoryProperties;
|
||||
}
|
||||
|
||||
@@ -282,7 +274,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Override
|
||||
public Page<DistributionSet> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, DistributionSetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetFields.class),
|
||||
DistributionSetSpecification.isNotDeleted()), pageable);
|
||||
}
|
||||
|
||||
@@ -551,8 +543,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
assertDsTagExists(tagId);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, DistributionSetFields.class, virtualPropertyReplacer,
|
||||
database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetFields.class),
|
||||
DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted()), pageable);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,13 +33,11 @@ import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTagSpeci
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.TagSpecification;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -54,17 +52,12 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
|
||||
|
||||
private final DistributionSetTagRepository distributionSetTagRepository;
|
||||
private final DistributionSetRepository distributionSetRepository;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final Database database;
|
||||
|
||||
public JpaDistributionSetTagManagement(
|
||||
final DistributionSetTagRepository distributionSetTagRepository,
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) {
|
||||
final DistributionSetRepository distributionSetRepository) {
|
||||
this.distributionSetTagRepository = distributionSetTagRepository;
|
||||
this.distributionSetRepository = distributionSetRepository;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,8 +148,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetTag> findByRsql(final String rsql, final Pageable pageable) {
|
||||
final Specification<JpaDistributionSetTag> spec = RsqlUtility.buildRsqlSpecification(
|
||||
rsql, DistributionSetTagFields.class, virtualPropertyReplacer, database);
|
||||
final Specification<JpaDistributionSetTag> spec = RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetTagFields.class);
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, Collections.singletonList(spec), pageable);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,12 +44,10 @@ import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpec
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -67,22 +65,17 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
|
||||
private final SoftwareModuleTypeRepository softwareModuleTypeRepository;
|
||||
private final DistributionSetRepository distributionSetRepository;
|
||||
private final TargetTypeRepository targetTypeRepository;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final Database database;
|
||||
private final QuotaManagement quotaManagement;
|
||||
|
||||
public JpaDistributionSetTypeManagement(
|
||||
final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
|
||||
final DistributionSetRepository distributionSetRepository, final TargetTypeRepository targetTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
|
||||
final QuotaManagement quotaManagement) {
|
||||
this.distributionSetTypeRepository = distributionSetTypeRepository;
|
||||
this.softwareModuleTypeRepository = softwareModuleTypeRepository;
|
||||
this.distributionSetRepository = distributionSetRepository;
|
||||
this.targetTypeRepository = targetTypeRepository;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.database = database;
|
||||
this.quotaManagement = quotaManagement;
|
||||
}
|
||||
|
||||
@@ -198,7 +191,7 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
|
||||
@Override
|
||||
public Page<DistributionSetType> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetTypeRepository, List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, DistributionSetTypeFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetTypeFields.class),
|
||||
DistributionSetTypeSpecification.isNotDeleted()), pageable);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,12 +48,10 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -70,24 +68,18 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
private final ActionRepository actionRepository;
|
||||
private final TargetRepository targetRepository;
|
||||
private final EntityManager entityManager;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final RolloutStatusCache rolloutStatusCache;
|
||||
private final Database database;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
public JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository,
|
||||
final RolloutRepository rolloutRepository, final ActionRepository actionRepository,
|
||||
final TargetRepository targetRepository, final EntityManager entityManager,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache,
|
||||
final Database database) {
|
||||
final TargetRepository targetRepository, final EntityManager entityManager, final RolloutStatusCache rolloutStatusCache) {
|
||||
this.rolloutGroupRepository = rolloutGroupRepository;
|
||||
this.rolloutRepository = rolloutRepository;
|
||||
this.actionRepository = actionRepository;
|
||||
this.targetRepository = targetRepository;
|
||||
this.entityManager = entityManager;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.rolloutStatusCache = rolloutStatusCache;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,8 +114,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
|
||||
|
||||
final List<Specification<JpaRolloutGroup>> specList = Arrays.asList(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, RolloutGroupFields.class, virtualPropertyReplacer,
|
||||
database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, RolloutGroupFields.class),
|
||||
(root, query, cb) -> cb.equal(root.get(JpaRolloutGroup_.rollout).get(AbstractJpaBaseEntity_.id), rolloutId));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, specList, pageable);
|
||||
@@ -189,7 +180,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = Arrays.asList(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
(root, query, cb) -> {
|
||||
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup);
|
||||
return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(AbstractJpaBaseEntity_.id), rolloutGroupId);
|
||||
|
||||
@@ -78,7 +78,6 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupsValidation;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -86,7 +85,6 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -120,10 +118,8 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||
private final QuotaManagement quotaManagement;
|
||||
private final AfterTransactionCommitExecutor afterCommit;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
private final ContextAware contextAware;
|
||||
private final Database database;
|
||||
private final RepositoryProperties repositoryProperties;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
@@ -139,8 +135,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final QuotaManagement quotaManagement,
|
||||
final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final Database database,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware,
|
||||
final RepositoryProperties repositoryProperties) {
|
||||
this.rolloutRepository = rolloutRepository;
|
||||
this.rolloutGroupRepository = rolloutGroupRepository;
|
||||
@@ -153,10 +148,8 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.afterCommit = afterCommit;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
this.contextAware = contextAware;
|
||||
this.database = database;
|
||||
this.repositoryProperties = repositoryProperties;
|
||||
}
|
||||
|
||||
@@ -273,7 +266,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Override
|
||||
public Page<Rollout> findByRsql(final String rsql, final boolean deleted, final Pageable pageable) {
|
||||
final List<Specification<JpaRollout>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, RolloutFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, RolloutFields.class),
|
||||
RolloutSpecification.isDeleted(deleted, pageable.getSort()));
|
||||
return JpaManagementHelper.convertPage(rolloutRepository.findAll(JpaManagementHelper.combineWithAnd(specList), pageable), pageable);
|
||||
}
|
||||
@@ -281,7 +274,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Override
|
||||
public Page<Rollout> findByRsqlWithDetailedStatus(final String rsql, final boolean deleted, final Pageable pageable) {
|
||||
final List<Specification<JpaRollout>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, RolloutFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, RolloutFields.class),
|
||||
RolloutSpecification.isDeleted(deleted, pageable.getSort()));
|
||||
return appendStatusDetails(JpaManagementHelper.convertPage(
|
||||
rolloutRepository.findAll(JpaManagementHelper.combineWithAnd(specList), JpaRollout_.GRAPH_ROLLOUT_DS, pageable), pageable));
|
||||
|
||||
@@ -58,7 +58,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -66,7 +65,6 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -89,8 +87,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
private final AuditorAware<String> auditorProvider;
|
||||
private final ArtifactManagement artifactManagement;
|
||||
private final QuotaManagement quotaManagement;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final Database database;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
public JpaSoftwareModuleManagement(final EntityManager entityManager,
|
||||
@@ -98,9 +94,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final SoftwareModuleMetadataRepository softwareModuleMetadataRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository, final AuditorAware<String> auditorProvider,
|
||||
final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final Database database) {
|
||||
final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement) {
|
||||
this.entityManager = entityManager;
|
||||
this.distributionSetRepository = distributionSetRepository;
|
||||
this.softwareModuleRepository = softwareModuleRepository;
|
||||
@@ -109,8 +103,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
this.auditorProvider = auditorProvider;
|
||||
this.artifactManagement = artifactManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,8 +253,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
@Override
|
||||
public Page<SoftwareModule> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, SoftwareModuleFields.class, virtualPropertyReplacer,
|
||||
database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, SoftwareModuleFields.class),
|
||||
SoftwareModuleSpecification.isNotDeleted()), pageable);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,10 @@ import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepositor
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleTypeSpecification;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -51,20 +49,15 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
|
||||
|
||||
private final DistributionSetTypeRepository distributionSetTypeRepository;
|
||||
private final SoftwareModuleTypeRepository softwareModuleTypeRepository;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final SoftwareModuleRepository softwareModuleRepository;
|
||||
private final Database database;
|
||||
|
||||
public JpaSoftwareModuleTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
public JpaSoftwareModuleTypeManagement(
|
||||
final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final Database database) {
|
||||
final SoftwareModuleRepository softwareModuleRepository) {
|
||||
this.distributionSetTypeRepository = distributionSetTypeRepository;
|
||||
this.softwareModuleTypeRepository = softwareModuleTypeRepository;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.softwareModuleRepository = softwareModuleRepository;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,8 +137,7 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
|
||||
@Override
|
||||
public Page<SoftwareModuleType> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, SoftwareModuleTypeFields.class,
|
||||
virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, SoftwareModuleTypeFields.class),
|
||||
SoftwareModuleTypeSpecification.isNotDeleted()), pageable
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import cz.jirutka.rsql.parser.RSQLParserException;
|
||||
@@ -51,7 +50,6 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
@@ -60,7 +58,6 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -77,7 +74,6 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final TargetManagement targetManagement;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final QuotaManagement quotaManagement;
|
||||
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||
@@ -85,29 +81,23 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
private final ContextAware contextAware;
|
||||
private final AuditorAware<String> auditorAware;
|
||||
private final EntityManager entityManager;
|
||||
private final Database database;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetManagement targetManagement, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||
final Database database, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
public JpaTargetFilterQueryManagement(
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement,
|
||||
final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final RepositoryProperties repositoryProperties,
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware,
|
||||
final EntityManager entityManager) {
|
||||
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) {
|
||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||
this.targetManagement = targetManagement;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.database = database;
|
||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||
this.repositoryProperties = repositoryProperties;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
this.contextAware = contextAware;
|
||||
this.auditorAware = auditorAware;
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,7 +109,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
|
||||
create.getQuery().ifPresent(query -> {
|
||||
// validate the RSQL query syntax
|
||||
RsqlUtility.validateRsqlFor(query, TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
|
||||
|
||||
// enforce the 'max targets per auto assign' quota right here even
|
||||
// if the result of the filter query can vary over time
|
||||
@@ -148,7 +138,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
@Override
|
||||
public boolean verifyTargetFilterQuerySyntax(final String query) {
|
||||
try {
|
||||
RsqlUtility.validateRsqlFor(query, TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
|
||||
return true;
|
||||
} catch (final RSQLParserException | RSQLParameterUnsupportedFieldException e) {
|
||||
log.debug("The RSQL query '{}}' is invalid.", query, e);
|
||||
@@ -195,8 +185,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
@Override
|
||||
public Page<TargetFilterQuery> findByRsql(final String rsqlFilter, final Pageable pageable) {
|
||||
final List<Specification<JpaTargetFilterQuery>> specList = !ObjectUtils.isEmpty(rsqlFilter)
|
||||
? Collections.singletonList(RsqlUtility.buildRsqlSpecification(rsqlFilter,
|
||||
TargetFilterQueryFields.class, virtualPropertyReplacer, database))
|
||||
? Collections.singletonList(RsqlUtility.getInstance().buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class))
|
||||
: Collections.emptyList();
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, specList, pageable);
|
||||
@@ -227,8 +216,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
final List<Specification<JpaTargetFilterQuery>> specList = new ArrayList<>(2);
|
||||
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
|
||||
if (!ObjectUtils.isEmpty(rsql)) {
|
||||
specList.add(RsqlUtility.buildRsqlSpecification(rsql, TargetFilterQueryFields.class,
|
||||
virtualPropertyReplacer, database));
|
||||
specList.add(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFilterQueryFields.class));
|
||||
}
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, specList, pageable);
|
||||
|
||||
@@ -74,14 +74,12 @@ import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -104,8 +102,6 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final TargetTagRepository targetTagRepository;
|
||||
private final TenantAware tenantAware;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final Database database;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
public JpaTargetManagement(final EntityManager entityManager,
|
||||
@@ -114,8 +110,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final RolloutGroupRepository rolloutGroupRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetTagRepository targetTagRepository,
|
||||
final TenantAware tenantAware, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final Database database) {
|
||||
final TenantAware tenantAware) {
|
||||
this.entityManager = entityManager;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
@@ -125,8 +120,6 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||
this.targetTagRepository = targetTagRepository;
|
||||
this.tenantAware = tenantAware;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,22 +150,20 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
public long countByRsql(final String rsql) {
|
||||
return JpaManagementHelper.countBySpec(
|
||||
targetRepository,
|
||||
List.of(RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database)));
|
||||
List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndUpdatable(String rsql) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database));
|
||||
return targetRepository.count(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(specList));
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class));
|
||||
return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndCompatible(final String rsql, final Long distributionSetIdTypeId) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
|
||||
return JpaManagementHelper.countBySpec(targetRepository, specList);
|
||||
}
|
||||
@@ -180,7 +171,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Override
|
||||
public long countByRsqlAndCompatibleAndUpdatable(String rsql, Long distributionSetIdTypeId) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
|
||||
return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
|
||||
}
|
||||
@@ -253,7 +244,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
.findAllWithoutCount(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))),
|
||||
pageable)
|
||||
@@ -268,8 +259,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return targetRepository.count(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.buildRsqlSpecification(
|
||||
rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))));
|
||||
}
|
||||
@@ -280,7 +270,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return targetRepository
|
||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))),
|
||||
pageable)
|
||||
@@ -292,7 +282,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final String rsql, final Collection<Long> groups, final DistributionSetType dsType) {
|
||||
return targetRepository.count(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
|
||||
}
|
||||
@@ -319,7 +309,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return targetRepository
|
||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasNoOverridingActionsAndNotInRollout(rolloutId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetType.getId()))),
|
||||
pageable)
|
||||
@@ -355,7 +345,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, specList, pageable);
|
||||
@@ -395,7 +385,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, specList, pageable);
|
||||
@@ -416,7 +406,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
public Slice<Target> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||
targetRepository,
|
||||
List.of(RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database)), pageable
|
||||
List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class)), pageable
|
||||
);
|
||||
}
|
||||
|
||||
@@ -426,8 +416,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
||||
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||
targetRepository, List.of(RsqlUtility.buildRsqlSpecification(
|
||||
targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer, database)), pageable
|
||||
targetRepository, List.of(RsqlUtility.getInstance().buildRsqlSpecification(
|
||||
targetFilterQuery.getQuery(), TargetFields.class)), pageable
|
||||
);
|
||||
}
|
||||
|
||||
@@ -442,7 +432,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
TargetSpecifications.hasTag(tagId));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, specList, pageable);
|
||||
@@ -611,12 +601,12 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Override
|
||||
public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
final String controllerId, final long distributionSetId, final String targetFilterQuery) {
|
||||
RsqlUtility.validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.getInstance().validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class);
|
||||
final DistributionSet ds = distributionSetManagement.get(distributionSetId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distributionSetId));
|
||||
final Long distSetTypeId = ds.getType().getId();
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(targetFilterQuery, TargetFields.class),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId),
|
||||
TargetSpecifications.hasControllerId(controllerId));
|
||||
|
||||
@@ -29,11 +29,9 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -48,16 +46,8 @@ public class JpaTargetTagManagement implements TargetTagManagement {
|
||||
|
||||
private final TargetTagRepository targetTagRepository;
|
||||
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final Database database;
|
||||
|
||||
public JpaTargetTagManagement(
|
||||
final TargetTagRepository targetTagRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final Database database) {
|
||||
this.targetTagRepository = targetTagRepository;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.database = database;
|
||||
public JpaTargetTagManagement(final TargetTagRepository targetTagRepository) {
|
||||
this.targetTagRepository = targetTagRepository;;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,7 +95,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
|
||||
@Override
|
||||
public Page<TargetTag> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, Collections.singletonList(
|
||||
RsqlUtility.buildRsqlSpecification(rsql, TargetTagFields.class, virtualPropertyReplacer, database)), pageable);
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetTagFields.class)), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,12 +38,10 @@ import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -60,9 +58,6 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
|
||||
private final TargetRepository targetRepository;
|
||||
private final DistributionSetTypeRepository distributionSetTypeRepository;
|
||||
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
|
||||
private final Database database;
|
||||
private final QuotaManagement quotaManagement;
|
||||
|
||||
/**
|
||||
@@ -70,18 +65,13 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
|
||||
*
|
||||
* @param targetTypeRepository Target type repository
|
||||
* @param targetRepository Target repository
|
||||
* @param virtualPropertyReplacer replacer
|
||||
* @param database database
|
||||
*/
|
||||
public JpaTargetTypeManagement(final TargetTypeRepository targetTypeRepository,
|
||||
final TargetRepository targetRepository, final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
|
||||
final QuotaManagement quotaManagement) {
|
||||
this.targetTypeRepository = targetTypeRepository;
|
||||
this.targetRepository = targetRepository;
|
||||
this.distributionSetTypeRepository = distributionSetTypeRepository;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.database = database;
|
||||
this.quotaManagement = quotaManagement;
|
||||
}
|
||||
|
||||
@@ -145,10 +135,10 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
|
||||
|
||||
@Override
|
||||
public Page<TargetType> findByRsql(final String rsql, final Pageable pageable) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetTypeRepository, List.of(
|
||||
RsqlUtility.buildRsqlSpecification(
|
||||
rsql, TargetTypeFields.class, virtualPropertyReplacer, database)), pageable
|
||||
);
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
targetTypeRepository,
|
||||
List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetTypeFields.class)),
|
||||
pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,7 +12,7 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
@@ -69,7 +69,7 @@ import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
||||
@@ -1091,7 +1091,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void findTargetsByRsqlWithTypeAndMetadata() {
|
||||
if (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G1) {
|
||||
if (RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G1) {
|
||||
// legacy visitor fail with that
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -11,14 +11,12 @@ package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G2;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G2;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TargetTypeFields;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
@@ -28,11 +26,9 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Slice;
|
||||
|
||||
/**
|
||||
@@ -45,11 +41,6 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
private static final String OR = ",";
|
||||
private static final String AND = ";";
|
||||
|
||||
@Autowired
|
||||
protected VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
@Autowired
|
||||
protected EntityManager entityManager;
|
||||
|
||||
private Target target;
|
||||
private Target target2;
|
||||
private TargetType targetType1;
|
||||
@@ -189,7 +180,7 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null==null", 1); // "null" check
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.n/a==null", 0); // "null" check
|
||||
|
||||
if (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
if (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.dot=is=value.dot", 1);
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null=is=null", 5); // null check
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.n/a=is=null", 1 + 5); // null check
|
||||
@@ -203,22 +194,22 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null!=null2", 1); // value check
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.n/a!=null", 0); // "null" check
|
||||
|
||||
if (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
if (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
assertRSQLQuery(
|
||||
TargetFields.ATTRIBUTE.name() + ".test.dot=not=value.dot",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0);
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null=not=null", 1); // null check
|
||||
assertRSQLQuery(
|
||||
TargetFields.ATTRIBUTE.name() + ".test.null=not=null2",
|
||||
1 + (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check
|
||||
1 + (RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.n/a=not=null", 0); // null check
|
||||
assertRSQLQuery(
|
||||
TargetFields.ATTRIBUTE.name() + ".test.dot=ne=value.dot",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0);
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null=ne=null", 1); // null check
|
||||
assertRSQLQuery(
|
||||
TargetFields.ATTRIBUTE.name() + ".test.null=ne=null2",
|
||||
1 + (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check
|
||||
1 + (RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.n/a=ne=null", 0); // null check
|
||||
}
|
||||
|
||||
@@ -315,7 +306,7 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".notExist==metaValue", 0);
|
||||
|
||||
if (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
if (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=is=metaValue", 1);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=is=null", 4); // null check (1 of the initial five has)
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=is=*v*", 2);
|
||||
@@ -333,27 +324,27 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".notExist!=metaValue", 0);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey!=notExist", 2);
|
||||
|
||||
if (RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
if (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) {
|
||||
assertRSQLQuery(
|
||||
TargetFields.METADATA.name() + ".metaKey=not=metaValue",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 4 : 1);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 4 : 1);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=not=null", 2); // null check (2 of the initial five)
|
||||
assertRSQLQuery(
|
||||
TargetFields.METADATA.name() + ".notExist=not=metaValue",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0);
|
||||
assertRSQLQuery(
|
||||
TargetFields.METADATA.name() + ".metaKey=not=notExist",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2);
|
||||
assertRSQLQuery(
|
||||
TargetFields.METADATA.name() + ".metaKey=ne=metaValue",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 4 : 1);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 4 : 1);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=ne=null", 2); // null check (2 of the initial five)
|
||||
assertRSQLQuery(
|
||||
TargetFields.METADATA.name() + ".notExist=ne=metaValue",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0);
|
||||
assertRSQLQuery(
|
||||
TargetFields.METADATA.name() + ".metaKey=ne=notExist",
|
||||
RsqlConfigHolder.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2);
|
||||
RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2);
|
||||
}
|
||||
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=in=(metaValue,notexist)", 1);
|
||||
@@ -386,28 +377,26 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void rsqlValidTargetFields() {
|
||||
RsqlUtility.validateRsqlFor(
|
||||
RsqlUtility.getInstance().validateRsqlFor(
|
||||
"ID == '0123' and NAME == abcd and DESCRIPTION == absd and CREATEDAT =lt= 0123 and LASTMODIFIEDAT =gt= 0123" +
|
||||
" and CONTROLLERID == 0123 and UPDATESTATUS == PENDING and IPADDRESS == 0123 and LASTCONTROLLERREQUESTAT == 0123" +
|
||||
" and tag == beta",
|
||||
TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.validateRsqlFor(
|
||||
TargetFields.class, JpaTarget.class);
|
||||
RsqlUtility.getInstance().validateRsqlFor(
|
||||
"ASSIGNEDDS.name == abcd and ASSIGNEDDS.version == 0123 and INSTALLEDDS.name == abcd and INSTALLEDDS.version == 0123",
|
||||
TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.validateRsqlFor(
|
||||
TargetFields.class, JpaTarget.class);
|
||||
RsqlUtility.getInstance().validateRsqlFor(
|
||||
"ATTRIBUTE.subkey1 == test and ATTRIBUTE.subkey2 == test and METADATA.metakey1 == abcd and METADATA.metavalue2 == asdfg",
|
||||
TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.validateRsqlFor(
|
||||
TargetFields.class, JpaTarget.class);
|
||||
RsqlUtility.getInstance().validateRsqlFor(
|
||||
"CREATEDAT =lt= ${NOW_TS} and LASTMODIFIEDAT =ge= ${OVERDUE_TS}",
|
||||
TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
RsqlUtility.validateRsqlFor(
|
||||
TargetFields.class, JpaTarget.class);
|
||||
RsqlUtility.getInstance().validateRsqlFor(
|
||||
"ATTRIBUTE.test.dot == test and ATTRIBUTE.subkey2 == test and METADATA.test.dot == abcd and METADATA.metavalue2 == asdfg",
|
||||
TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
TargetFields.class, JpaTarget.class);
|
||||
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.isThrownBy(() -> RsqlUtility.validateRsqlFor(
|
||||
"wrongfield == abcd",
|
||||
TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager));
|
||||
.isThrownBy(() -> RsqlUtility.getInstance().validateRsqlFor("wrongfield == abcd", TargetFields.class, JpaTarget.class));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,7 +441,6 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private void assertRSQLQueryThrowsException(final String rsql) {
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.isThrownBy(() -> RsqlUtility.validateRsqlFor(
|
||||
rsql, TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager));
|
||||
.isThrownBy(() -> RsqlUtility.getInstance().validateRsqlFor(rsql, TargetFields.class, JpaTarget.class));
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G2;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.G3;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlConfigHolder.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G2;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.G3;
|
||||
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
@@ -1,497 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Path;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import jakarta.persistence.metamodel.Attribute;
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import jakarta.persistence.metamodel.Type;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
|
||||
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
/**
|
||||
* Feature: Component Tests - Repository<br/>
|
||||
* Story: RSQL search utility
|
||||
*/
|
||||
@Disabled
|
||||
// TODO: fully document tests -> description for long text and reasonable
|
||||
// method name as short text
|
||||
class RsqlUtilityTest {
|
||||
|
||||
private static final TenantConfigurationValue<String> TEST_POLLING_TIME_INTERVAL =
|
||||
TenantConfigurationValue.<String> builder().value("00:05:00").build();
|
||||
private static final TenantConfigurationValue<String> TEST_POLLING_OVERDUE_TIME_INTERVAL =
|
||||
TenantConfigurationValue.<String> builder().value("00:07:37").build();
|
||||
|
||||
@Spy
|
||||
private final VirtualPropertyResolver macroResolver = new VirtualPropertyResolver();
|
||||
private final Database testDb = Database.H2;
|
||||
@MockitoBean
|
||||
private TenantConfigurationManagement confMgmt;
|
||||
@MockitoBean
|
||||
private SystemSecurityContext securityContext;
|
||||
@Mock
|
||||
private Root<Object> baseSoftwareModuleRootMock;
|
||||
@Mock
|
||||
private CriteriaQuery<SoftwareModule> criteriaQueryMock;
|
||||
@Mock
|
||||
private CriteriaBuilder criteriaBuilderMock;
|
||||
@Mock
|
||||
private Subquery<SoftwareModule> subqueryMock;
|
||||
@Mock
|
||||
private Root<SoftwareModule> subqueryRootMock;
|
||||
@Mock
|
||||
private Attribute attribute;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
setupRoot(baseSoftwareModuleRootMock);
|
||||
setupRoot(subqueryRootMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrongFieldThrowUnsupportedFieldException() {
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
final Specification<Object> rsqlSpecification = RsqlUtility.buildRsqlSpecification("unknownField==abc", SoftwareModuleFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterUnsupportedFieldException because of unknown RSQL field")
|
||||
.isThrownBy(() -> rsqlSpecification.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrongRsqlMapSyntaxThrowSyntaxException() {
|
||||
final Specification<Object> rsqlSpecification =
|
||||
RsqlUtility.buildRsqlSpecification(TargetFields.ATTRIBUTE + "==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException for target attributes map, caused by wrong RSQL syntax (key was not present)")
|
||||
.isThrownBy(() -> rsqlSpecification.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
|
||||
final Specification<Object> rsqlSpecification2 =
|
||||
RsqlUtility.buildRsqlSpecification(TargetFields.ATTRIBUTE + ".unknown.wrong==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException for target attributes map, caused by wrong RSQL syntax (key includes dots)")
|
||||
.isThrownBy(() -> rsqlSpecification2.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
|
||||
final Specification<Object> rsqlSpecification3 =
|
||||
RsqlUtility.buildRsqlSpecification(TargetFields.METADATA + ".unknown.wrong==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException for target metadata map, caused by wrong RSQL syntax (key includes dots)")
|
||||
.isThrownBy(() -> rsqlSpecification3.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
|
||||
final Specification<Object> rsqlSpecification4 =
|
||||
RsqlUtility.buildRsqlSpecification(DistributionSetFields.METADATA + "==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException for distribution set metadata map, caused by wrong RSQL syntax (key was not present)\"")
|
||||
.isThrownBy(() -> rsqlSpecification4.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrongRsqlSubEntitySyntaxThrowSyntaxException() {
|
||||
final Specification<Object> rsqlSpecification =
|
||||
RsqlUtility.buildRsqlSpecification(TargetFields.ASSIGNEDDS + "==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException because of wrong RSQL syntax")
|
||||
.isThrownBy(() -> rsqlSpecification.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
|
||||
final Specification<Object> rsqlSpecification2 =
|
||||
RsqlUtility.buildRsqlSpecification(TargetFields.ASSIGNEDDS + ".unknownField==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException because of wrong RSQL syntax")
|
||||
.isThrownBy(() -> rsqlSpecification2.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
|
||||
final Specification<Object> rsqlSpecification3 =
|
||||
RsqlUtility.buildRsqlSpecification(TargetFields.ASSIGNEDDS + ".unknownField.ToMuch==abc", TargetFields.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterSyntaxException because of wrong RSQL syntax")
|
||||
.isThrownBy(() -> rsqlSpecification3.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
<T> void correctRsqlBuildsPredicate() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==abc;version==1.2";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.get("version")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
when(criteriaBuilderMock.like(any(Expression.class), anyString(), eq('\\'))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.equal(any(Expression.class), any(String.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.and(any(Predicate[].class))).thenReturn(mock(Predicate.class));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlBuildsSimpleNotEqualPredicate() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name!=abc";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
|
||||
when(criteriaBuilderMock.isNull(any(Expression.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.notEqual(any(Expression.class), anyString())).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).or(any(Predicate.class), any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).isNull(pathOfString(baseSoftwareModuleRootMock));
|
||||
verify(criteriaBuilderMock, times(1)).notEqual(pathOfString(baseSoftwareModuleRootMock), "abc".toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlBuildsSimpleNotLikePredicate() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name!=abc*";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
|
||||
when(criteriaBuilderMock.isNull(any(Expression.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.notLike(any(Expression.class), anyString(), eq('\\')))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).or(any(Predicate.class), any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).isNull(pathOfString(baseSoftwareModuleRootMock));
|
||||
verify(criteriaBuilderMock, times(1)).notLike(pathOfString(baseSoftwareModuleRootMock), "abc%".toUpperCase(), '\\');
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlBuildsNotSimpleNotLikePredicate() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
// with this query a subquery has to be made, so it is no simple query
|
||||
final String correctRsql = "type!=abc";
|
||||
when(baseSoftwareModuleRootMock.get(anyString())).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
|
||||
final Path pathMock = mock(Path.class);
|
||||
when(pathMock.get(anyString())).thenReturn(pathMock);
|
||||
when(subqueryRootMock.get(anyString())).thenReturn(pathMock);
|
||||
|
||||
when(criteriaBuilderMock.and(any(), any())).thenReturn(mock(Predicate.class));
|
||||
|
||||
when(criteriaQueryMock.subquery(SoftwareModule.class)).thenReturn(subqueryMock);
|
||||
|
||||
when(subqueryMock.from(SoftwareModule.class)).thenReturn(subqueryRootMock);
|
||||
when(subqueryMock.select(subqueryRootMock)).thenReturn(subqueryMock);
|
||||
when(subqueryMock.where(any(Expression.class))).thenReturn(subqueryMock);
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).not(criteriaBuilderMock.exists(eq(subqueryMock)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlBuildsEqualPredicateWithPercentage() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==a%";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
when(criteriaBuilderMock.equal(any(Expression.class), anyString())).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, Database.H2)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).equal(pathOfString(baseSoftwareModuleRootMock), "a%".toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlBuildsLikePredicateWithPercentage() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==a%*";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
when(criteriaBuilderMock.like(any(Expression.class), anyString(), eq('\\'))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, Database.H2)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).like(pathOfString(baseSoftwareModuleRootMock), "a\\%%".toUpperCase(), '\\');
|
||||
}
|
||||
|
||||
// MsSQL is not officially supported
|
||||
// thought it may be available through configuration and adding necessarily dependencies
|
||||
// so we keep RSQL compatibility testing
|
||||
@Test
|
||||
void correctRsqlBuildsLikePredicateWithPercentageSQLServer() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==a%*";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
when(criteriaBuilderMock.like(any(Expression.class), anyString(), eq('\\'))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(mock(Predicate.class));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, Database.SQL_SERVER)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).like(pathOfString(baseSoftwareModuleRootMock), "a[%]%".toUpperCase(), '\\');
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlBuildsLessThanPredicate() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name=lt=abc";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
when(criteriaBuilderMock.lessThan(any(Expression.class), anyString())).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).lessThan(pathOfString(baseSoftwareModuleRootMock), "abc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void correctRsqlWithEnumValue() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "testfield==bumlux";
|
||||
when(baseSoftwareModuleRootMock.get("testfield")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
|
||||
when(criteriaBuilderMock.equal(any(Root.class), any(TestValueEnum.class))).thenReturn(mock(Predicate.class));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, TestFieldEnum.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).equal(baseSoftwareModuleRootMock, TestValueEnum.BUMLUX);
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrongRsqlWithWrongEnumValue() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "testfield==unknownValue";
|
||||
when(baseSoftwareModuleRootMock.get("testfield")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
|
||||
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
||||
|
||||
final Specification<Object> rsqlSpecification = RsqlUtility.buildRsqlSpecification(correctRsql, TestFieldEnum.class, null, testDb);
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.as("RSQLParameterUnsupportedFieldException for wrong enum value")
|
||||
.isThrownBy(() -> rsqlSpecification.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the resolution of overdue_ts placeholder in context of a RSQL expression.
|
||||
*/
|
||||
@Test
|
||||
void correctRsqlWithOverdueMacro() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String overdueProp = "overdue_ts";
|
||||
final String overduePropPlaceholder = "${" + overdueProp + "}";
|
||||
final String correctRsql = "testfield=le=" + overduePropPlaceholder;
|
||||
when(baseSoftwareModuleRootMock.get("testfield")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
when(criteriaBuilderMock.upper(pathOfString(baseSoftwareModuleRootMock))).thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
when(criteriaBuilderMock.like(any(Expression.class), anyString(), eq('\\'))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.lessThanOrEqualTo(any(Expression.class), eq(overduePropPlaceholder))).thenReturn(mock(Predicate.class));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, TestFieldEnum.class, setupMacroLookup(), testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
// the macro is already replaced when passed to #lessThanOrEqualTo -> the method is never invoked with the placeholder:
|
||||
verify(criteriaBuilderMock, never()).lessThanOrEqualTo(pathOfString(baseSoftwareModuleRootMock), overduePropPlaceholder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests RSQL expression with an unknown placeholder.
|
||||
*/
|
||||
@Test
|
||||
void correctRsqlWithUnknownMacro() {
|
||||
reset0(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String overdueProp = "unknown";
|
||||
final String overduePropPlaceholder = "${" + overdueProp + "}";
|
||||
final String correctRsql = "testfield=le=" + overduePropPlaceholder;
|
||||
when(baseSoftwareModuleRootMock.get("testfield")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
|
||||
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.<String> lessThanOrEqualTo(any(Expression.class), eq(overduePropPlaceholder)))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
|
||||
// test
|
||||
RsqlUtility.buildRsqlSpecification(correctRsql, TestFieldEnum.class, setupMacroLookup(), testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
// the macro is unknown and hence never replaced -> #lessThanOrEqualTo is invoked with the placeholder:
|
||||
verify(criteriaBuilderMock).lessThanOrEqualTo(pathOfString(baseSoftwareModuleRootMock), overduePropPlaceholder);
|
||||
}
|
||||
|
||||
VirtualPropertyReplacer setupMacroLookup() {
|
||||
when(securityContext.runAsSystem(Mockito.any())).thenAnswer(a -> ((Callable<?>) a.getArgument(0)).call());
|
||||
|
||||
when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_TIME, String.class))
|
||||
.thenReturn(TEST_POLLING_TIME_INTERVAL);
|
||||
when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME, String.class))
|
||||
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
|
||||
|
||||
return macroResolver;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <Y> Path<Y> pathOfString(final Path<?> path) {
|
||||
return (Path<Y>) path;
|
||||
}
|
||||
|
||||
private void reset0(final Object... mocks) {
|
||||
reset(mocks);
|
||||
if (Arrays.asList(mocks).contains(baseSoftwareModuleRootMock)) {
|
||||
setupRoot(baseSoftwareModuleRootMock);
|
||||
}
|
||||
if (Arrays.asList(mocks).contains(subqueryRootMock)) {
|
||||
setupRoot(subqueryRootMock);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void setupRoot(final Root<?> root) {
|
||||
final Type type = Mockito.mock(Type.class);
|
||||
when(type.getPersistenceType()).thenReturn(Type.PersistenceType.BASIC);
|
||||
final SingularAttribute singularAttribute = Mockito.mock(SingularAttribute.class);
|
||||
when(singularAttribute.getType()).thenReturn(type);
|
||||
final EntityType entityType = Mockito.mock(EntityType.class);
|
||||
when(entityType.getAttribute(any())).thenReturn(singularAttribute);
|
||||
when(entityType.getPersistenceType()).thenReturn(Type.PersistenceType.BASIC);
|
||||
when(root.getModel()).thenReturn(entityType);
|
||||
}
|
||||
|
||||
private enum TestFieldEnum implements RsqlQueryField {
|
||||
TESTFIELD("testfield"), TESTFIELD_WITH_SUB_ENTITIES("testfieldWithSubEntities", "subentity11", "subentity22");
|
||||
|
||||
private final String fieldName;
|
||||
private final List<String> subEntityAttributes;
|
||||
|
||||
TestFieldEnum(final String fieldName) {
|
||||
this(fieldName, new String[0]);
|
||||
}
|
||||
|
||||
TestFieldEnum(final String fieldName, final String... subEntityAttributes) {
|
||||
this.fieldName = fieldName;
|
||||
this.subEntityAttributes = (Arrays.asList(subEntityAttributes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJpaEntityFieldName() {
|
||||
return this.fieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSubEntityAttributes() {
|
||||
return subEntityAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
private enum TestValueEnum {
|
||||
BUMLUX;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
TenantConfigurationManagementHolder tenantConfigurationManagementHolder() {
|
||||
return TenantConfigurationManagementHolder.getInstance();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SystemSecurityContextHolder systemSecurityContextHolder() {
|
||||
return SystemSecurityContextHolder.getInstance();
|
||||
}
|
||||
|
||||
@Bean
|
||||
RsqlConfigHolder rsqlConfigHolder() {
|
||||
return RsqlConfigHolder.getInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user