diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java index 9adc630d9..686cda9ae 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java @@ -17,7 +17,7 @@ import lombok.Getter; * Sort and search fields for actions. */ @Getter -public enum ActionFields implements RsqlQueryField, FieldValueConverter { +public enum ActionFields implements QueryField, FieldValueConverter { ID("id"), STATUS("active"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java index 28701e99c..f07291d2a 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java @@ -15,7 +15,7 @@ import lombok.Getter; * Sort and search fields for action status. */ @Getter -public enum ActionStatusFields implements RsqlQueryField { +public enum ActionStatusFields implements QueryField { ID("id"), @Deprecated diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetFields.java index 0cec77bbd..47be44205 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetFields.java @@ -18,7 +18,7 @@ import lombok.Getter; * REST API e.g. for sorting etc. */ @Getter -public enum DistributionSetFields implements RsqlQueryField { +public enum DistributionSetFields implements QueryField { ID("id"), TYPE("type", @@ -48,7 +48,7 @@ public enum DistributionSetFields implements RsqlQueryField { @Override public String getDefaultSubEntityAttribute() { - return this == TYPE ? DistributionSetTypeFields.KEY.getJpaEntityFieldName() : RsqlQueryField.super.getDefaultSubEntityAttribute(); + return this == TYPE ? DistributionSetTypeFields.KEY.getJpaEntityFieldName() : QueryField.super.getDefaultSubEntityAttribute(); } @Override diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagFields.java index cd56cf981..ca21b3bf7 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagFields.java @@ -20,7 +20,7 @@ import lombok.Getter; * filtering over distribution set fields also. */ @Getter -public enum DistributionSetTagFields implements RsqlQueryField { +public enum DistributionSetTagFields implements QueryField { ID(TagFields.ID.getJpaEntityFieldName()), NAME(TagFields.NAME.getJpaEntityFieldName()), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeFields.java index 42f792dca..381ee70db 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeFields.java @@ -16,7 +16,7 @@ import lombok.Getter; * the REST API e.g. for sorting etc. */ @Getter -public enum DistributionSetTypeFields implements RsqlQueryField { +public enum DistributionSetTypeFields implements QueryField { ID("id"), KEY("key"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RsqlQueryField.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/QueryField.java similarity index 93% rename from hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RsqlQueryField.java rename to hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/QueryField.java index 9ec676c0d..08066aece 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RsqlQueryField.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/QueryField.java @@ -16,9 +16,9 @@ import java.util.Map; import jakarta.validation.constraints.NotNull; /** - * An RSQL query field interface extended by all the fields that could be used in RSQL queries. + * A query field interface extended by all the fields that could be used in queries. */ -public interface RsqlQueryField { +public interface QueryField { /** * Separator for the sub attributes diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutFields.java index 33b75ffab..3c1e4d47e 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutFields.java @@ -17,7 +17,7 @@ import lombok.Getter; * Describing the fields of the Rollout model which can be used in the REST API e.g. for sorting etc. */ @Getter -public enum RolloutFields implements RsqlQueryField { +public enum RolloutFields implements QueryField { ID("id"), NAME("name"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupFields.java index 775fef78e..f6716c728 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupFields.java @@ -15,7 +15,7 @@ import lombok.Getter; * Describing the fields of the RolloutGroup model which can be used in the REST API e.g. for sorting etc. */ @Getter -public enum RolloutGroupFields implements RsqlQueryField { +public enum RolloutGroupFields implements QueryField { ID("id"), NAME("name"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java index 0729a0700..61103bf69 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleFields.java @@ -17,7 +17,7 @@ import lombok.Getter; * Describing the fields of the SoftwareModule model which can be used in the REST API e.g. for sorting etc. */ @Getter -public enum SoftwareModuleFields implements RsqlQueryField { +public enum SoftwareModuleFields implements QueryField { ID("id"), TYPE("type", @@ -44,7 +44,7 @@ public enum SoftwareModuleFields implements RsqlQueryField { @Override public String getDefaultSubEntityAttribute() { - return this == TYPE ? SoftwareModuleTypeFields.KEY.getJpaEntityFieldName() : RsqlQueryField.super.getDefaultSubEntityAttribute(); + return this == TYPE ? SoftwareModuleTypeFields.KEY.getJpaEntityFieldName() : QueryField.super.getDefaultSubEntityAttribute(); } @Override diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeFields.java index 650300633..0e2b6f3a9 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeFields.java @@ -15,7 +15,7 @@ import lombok.Getter; * Describing the fields of the SoftwareModuleType model which can be used in the REST API e.g. for sorting etc. */ @Getter -public enum SoftwareModuleTypeFields implements RsqlQueryField { +public enum SoftwareModuleTypeFields implements QueryField { ID("id"), KEY("key"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TagFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TagFields.java index a7bd48255..5379063f5 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TagFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TagFields.java @@ -15,7 +15,7 @@ import lombok.Getter; * Describing the fields of the Tag model which can be used in the REST API e.g. for sorting etc. */ @Getter -public enum TagFields implements RsqlQueryField { +public enum TagFields implements QueryField { ID("id"), NAME("name"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java index 0bbd287b7..91f81dc1c 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFields.java @@ -18,7 +18,7 @@ import lombok.Getter; * e.g. for sorting etc. */ @Getter -public enum TargetFields implements RsqlQueryField { +public enum TargetFields implements QueryField { ID("controllerId"), NAME("name"), @@ -62,7 +62,7 @@ public enum TargetFields implements RsqlQueryField { @Override public String getDefaultSubEntityAttribute() { - return this == TYPE ? TargetTypeFields.KEY.getJpaEntityFieldName() : RsqlQueryField.super.getDefaultSubEntityAttribute(); + return this == TYPE ? TargetTypeFields.KEY.getJpaEntityFieldName() : QueryField.super.getDefaultSubEntityAttribute(); } @Override diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryFields.java index 7a061e40a..bae4b3858 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryFields.java @@ -18,7 +18,7 @@ import lombok.Getter; * Describing the fields of the Target model which can be used in the REST API e.g. for sorting etc. */ @Getter -public enum TargetFilterQueryFields implements RsqlQueryField { +public enum TargetFilterQueryFields implements QueryField { ID("id"), NAME("name"), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java index c3fd56414..f66b86bc5 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTagFields.java @@ -16,7 +16,7 @@ import lombok.Getter; * Additionally, here were added fields for Target in order filtering over target fields also. */ @Getter -public enum TargetTagFields implements RsqlQueryField { +public enum TargetTagFields implements QueryField { ID(TagFields.ID.getJpaEntityFieldName()), NAME(TagFields.NAME.getJpaEntityFieldName()), diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTypeFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTypeFields.java index 25357b194..f4fc3e79b 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTypeFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/TargetTypeFields.java @@ -15,7 +15,7 @@ import lombok.Getter; * Describing the fields of the TargetType model which can be used in the REST API */ @Getter -public enum TargetTypeFields implements RsqlQueryField { +public enum TargetTypeFields implements QueryField { ID("id"), KEY("key"), diff --git a/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/RsqlQueryFieldsTest.java b/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/QueryFieldsTest.java similarity index 83% rename from hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/RsqlQueryFieldsTest.java rename to hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/QueryFieldsTest.java index 60e8fda8c..254ad48db 100644 --- a/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/RsqlQueryFieldsTest.java +++ b/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/QueryFieldsTest.java @@ -18,7 +18,7 @@ import io.github.classgraph.ClassInfo; import io.github.classgraph.ScanResult; import org.junit.jupiter.api.Test; -class RsqlQueryFieldsTest { +class QueryFieldsTest { /** * Verifies that fields classes are correctly implemented @@ -28,11 +28,11 @@ class RsqlQueryFieldsTest { void repositoryManagementMethodsArePreAuthorizedAnnotated() { final String packageName = getClass().getPackage().getName(); try (final ScanResult scanResult = new ClassGraph().acceptPackages(packageName).scan()) { - final List> matchingClasses = scanResult.getAllClasses() + final List> matchingClasses = scanResult.getAllClasses() .stream() - .filter(classInPackage -> classInPackage.implementsInterface(RsqlQueryField.class)) + .filter(classInPackage -> classInPackage.implementsInterface(QueryField.class)) .map(ClassInfo::loadClass) - .map(clazz -> (Class) clazz) + .map(clazz -> (Class) clazz) .toList(); assertThat(matchingClasses).isNotEmpty(); matchingClasses.forEach(providerClass -> assertThat(providerClass.getEnumConstants()).isNotEmpty()); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/SortUtility.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/SortUtility.java index d68a55e6e..7a236dbf9 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/SortUtility.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/util/SortUtility.java @@ -18,7 +18,7 @@ import lombok.NoArgsConstructor; import org.eclipse.hawkbit.mgmt.rest.resource.exception.SortParameterSyntaxErrorException; import org.eclipse.hawkbit.mgmt.rest.resource.exception.SortParameterUnsupportedDirectionException; import org.eclipse.hawkbit.mgmt.rest.resource.exception.SortParameterUnsupportedFieldException; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; @@ -44,15 +44,15 @@ public final class SortUtility { * sorting will be mapped into the {@link Direction} enum. * * @param enumType the class of the enum which the fields in the sort string should be related to. - * @param the type of the enumeration which must be derived from {@link RsqlQueryField} + * @param the type of the enumeration which must be derived from {@link QueryField} * @param sortString the string representation of the query parameters. Might be {@code null} or an empty string. - * @return a list which holds the {@link RsqlQueryField} and the specific {@link Direction} for them as a tuple. Never {@code null}. + * @return a list which holds the {@link QueryField} and the specific {@link Direction} for them as a tuple. Never {@code null}. * In case of no sorting parameters an empty map will be returned. * @throws SortParameterSyntaxErrorException if the sorting query parameter is not well-formed * @throws SortParameterUnsupportedFieldException if a field name cannot be mapped to the enum type * @throws SortParameterUnsupportedDirectionException if the given direction is not "ASC" or "DESC" */ - public static & RsqlQueryField> List parse(final Class enumType, final String sortString) + public static & QueryField> List parse(final Class enumType, final String sortString) throws SortParameterSyntaxErrorException { final List orders = new ArrayList<>(); // scan the sort tuples e.g. field:direction diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QueryException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QueryException.java new file mode 100644 index 000000000..0c6a66d53 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QueryException.java @@ -0,0 +1,41 @@ +/** + * 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.exception; + +import java.io.Serial; + +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.eclipse.hawkbit.exception.AbstractServerRtException; +import org.eclipse.hawkbit.exception.SpServerError; + +/** + * Exception used by the REST API in case of RSQL search filter query. + */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public abstract class QueryException extends AbstractServerRtException { + + QueryException(final SpServerError error) { + super(error); + } + + QueryException(final SpServerError error, final String message) { + super(error, message); + } + + QueryException(final SpServerError error, final Throwable cause) { + super(error, cause); + } + + QueryException(final SpServerError error, final String message, final Throwable cause) { + super(error, message, cause); + } +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java index a1b063b78..ae1f5bceb 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError; */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class RSQLParameterSyntaxException extends AbstractServerRtException { +public class RSQLParameterSyntaxException extends QueryException { @Serial private static final long serialVersionUID = 1L; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java index 020ed7734..3bfc00697 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError; */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class RSQLParameterUnsupportedFieldException extends AbstractServerRtException { +public class RSQLParameterUnsupportedFieldException extends QueryException { @Serial private static final long serialVersionUID = 1L; diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/Node.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/Node.java index eaf20f992..b7608c0ba 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/Node.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/Node.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.jpa.ql; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.function.UnaryOperator; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -38,6 +39,25 @@ public interface Node { return op(this, Logical.Operator.OR, other); } + // utility method that maps this node with a mapper that could modify comparisons - e.g. change keys, values, operators, or whatever + // if there are no changes the same instance is returned + default Node map(final UnaryOperator mapper) { + if (this instanceof Comparison comparison) { + return mapper.apply(comparison); + } else { + final List mappedChildren = new ArrayList<>(); + boolean modified = false; + for (final Node child : ((Logical) this).getChildren()) { + final Node mapped = child.map(mapper); + mappedChildren.add(mapped); + if (!mapped.equals(child)) { + modified = true; + } + } + return modified ? new Logical(((Logical) this).getOp(), mappedChildren) : this; + } + } + static Logical op(final Node node1, final Logical.Operator op, final Node node2) { if (node1 instanceof Logical logical1 && logical1.getOp() == op) { if (node2 instanceof Logical logical2 && logical2.getOp() == op) { // same op @@ -121,7 +141,7 @@ public interface Node { private final String symbol; - Operator(String symbol) { + Operator(final String symbol) { this.symbol = symbol; } diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlUtility.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/QLSupport.java similarity index 59% rename from hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlUtility.java rename to hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/QLSupport.java index 8cf6c67dc..1d732ba83 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlUtility.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/QLSupport.java @@ -7,23 +7,26 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.jpa.rsql; +package org.eclipse.hawkbit.repository.jpa.ql; + +import java.util.Objects; 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; +import org.eclipse.hawkbit.repository.QueryField; +import org.eclipse.hawkbit.repository.exception.QueryException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; -import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder; +import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison; +import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser; import org.eclipse.hawkbit.repository.jpa.rsql.legacy.SpecificationBuilderLegacy; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver; @@ -69,20 +72,20 @@ import org.springframework.orm.jpa.vendor.Database; @Slf4j @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class RsqlUtility { +public class QLSupport { - private static final RsqlUtility SINGLETON = new RsqlUtility(); + private static final QLSupport SINGLETON = new QLSupport(); - public enum RsqlToSpecBuilder { + public enum SpecBuilder { LEGACY_G1, // legacy RSQL visitor LEGACY_G2, // G2 RSQL visitor - G3 // G3 RSQL visitor - still experimental / yet default + G3 // G3 specification builder - still experimental / yet default } /** - * If RSQL comparison operators shall ignore the case. If ignore case is true "x == ax" will match "x == aX" + * If QL comparison operators shall ignore the case. If ignore case is true "x == ax" will match "x == aX" */ - @Value("${hawkbit.rsql.ignore-case:true}") + @Value("${hawkbit.ql.ignore-case:true}") private boolean ignoreCase; /** * Declares if the database is case-insensitive, by default assumes false. In case it is case-sensitive and, @@ -100,8 +103,10 @@ public class RsqlUtility { @Setter // for tests only @Deprecated(forRemoval = true, since = "0.6.0") @Value("${hawkbit.rsql.rsql-to-spec-builder:G3}") // - private RsqlToSpecBuilder rsqlToSpecBuilder; + private SpecBuilder specBuilder; + @SuppressWarnings({ "rawtypes", "unchecked" }) + private QueryParser parser; private VirtualPropertyReplacer virtualPropertyReplacer; private Database database; private EntityManager entityManager; @@ -109,10 +114,15 @@ public class RsqlUtility { /** * @return The holder singleton instance. */ - public static RsqlUtility getInstance() { + public static QLSupport getInstance() { return SINGLETON; } + @Autowired + void setQueryParser(final QueryParser parser) { + this.parser = parser; + } + @Autowired(required = false) void setVirtualPropertyReplacer(final VirtualPropertyReplacer virtualPropertyReplacer) { this.virtualPropertyReplacer = virtualPropertyReplacer; @@ -132,37 +142,71 @@ public class RsqlUtility { * Builds a JPA {@link Specification} which corresponds with the given RSQL query. The specification can be used to filter for JPA entities * with the given RSQL query. * - * @param rsql the rsql query to be parsed - * @param rsqlQueryFieldType the enum class type which implements the {@link RsqlQueryField} + * @param query the rsql query to be parsed + * @param queryFieldType the enum class type which implements the {@link QueryField} * @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 & RsqlQueryField, T> Specification buildRsqlSpecification( - final String rsql, final Class rsqlQueryFieldType) { - if (rsqlToSpecBuilder == RsqlToSpecBuilder.G3) { - return new SpecificationBuilder(virtualPropertyReplacer, !caseInsensitiveDB && ignoreCase, database) - .specification(RsqlParser.parse(caseInsensitiveDB || ignoreCase ? rsql.toLowerCase() : rsql, rsqlQueryFieldType)); + public & QueryField, T> Specification buildSpec( + final String query, final Class queryFieldType) { + if (specBuilder == SpecBuilder.G3) { + return new SpecificationBuilder(!caseInsensitiveDB && ignoreCase, database) + .specification(parser.parse(caseInsensitiveDB || ignoreCase ? query.toLowerCase() : query, queryFieldType)); } else { - return new SpecificationBuilderLegacy(rsqlQueryFieldType, virtualPropertyReplacer, database).specification(rsql); + return new SpecificationBuilderLegacy(queryFieldType, virtualPropertyReplacer, database).specification(query); } } /** - * Validates the RSQL string + * Validates the query string * - * @param rsql RSQL string to validate - * @param rsqlQueryFieldType the enum class type which implements the {@link RsqlQueryField} + * @param query query string to validate + * @param queryFieldType the enum class type which implements the {@link QueryField} * @param jpaType the JPA entity type to validate against - * @throws RSQLParserException if RSQL syntax is invalid - * @throws RSQLParameterUnsupportedFieldException if RSQL key is not allowed + * @throws QueryException if query is invalid */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public & RsqlQueryField> void validateRsqlFor( - final String rsql, final Class rsqlQueryFieldType, final Class jpaType) { + public & QueryField> void validateQuery(final String query, final Class queryFieldType, final Class jpaType) { final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(jpaType); - buildRsqlSpecification(rsql, rsqlQueryFieldType).toPredicate(criteriaQuery.from((Class) jpaType), criteriaQuery, criteriaBuilder); + buildSpec(query, queryFieldType).toPredicate(criteriaQuery.from((Class) jpaType), criteriaQuery, criteriaBuilder); + } + + public interface QueryParser { + + & QueryField> Node parse(final String query, final Class queryFieldType) throws QueryException; + } + + public static class DefaultQueryParser implements QueryParser { + + private VirtualPropertyReplacer virtualPropertyReplacer; + + @Autowired(required = false) + void setVirtualPropertyReplacer(final VirtualPropertyReplacer virtualPropertyReplacer) { + this.virtualPropertyReplacer = virtualPropertyReplacer; + } + + @Override + public & QueryField> Node parse(final String query, final Class queryFieldType) throws QueryException { + return RsqlParser.parse(query, queryFieldType).map(this::map); + } + + protected Comparison map(final Comparison comparison) { + final String key = mapKey(comparison.getKey(), comparison).toString(); + final Object value = mapValue(comparison.getValue(), comparison); + return key.equals(comparison.getKey()) && Objects.equals(value, comparison.getValue()) + ? comparison : Comparison.builder().key(key).op(comparison.getOp()).value(value).build(); + } + + // just extension points for subclasses + protected Object mapKey(final String key, final Comparison comparison) { + return key; + } + + protected Object mapValue(final Object value, final Comparison comparison) { + return value instanceof String strValue ? virtualPropertyReplacer.replace(strValue) : value; + } } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilder.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilder.java index 914daa00b..1c3e2a360 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilder.java @@ -63,14 +63,10 @@ public class SpecificationBuilder { private static final char ESCAPE_CHAR = '\\'; - private final VirtualPropertyReplacer virtualPropertyReplacer; private final boolean ensureIgnoreCase; private final Database database; - public SpecificationBuilder( - final VirtualPropertyReplacer virtualPropertyReplacer, - final boolean ensureIgnoreCase, final Database database) { - this.virtualPropertyReplacer = virtualPropertyReplacer; + public SpecificationBuilder(final boolean ensureIgnoreCase, final Database database) { this.ensureIgnoreCase = ensureIgnoreCase; this.database = database; } @@ -244,10 +240,6 @@ public class SpecificationBuilder { private List getValues(final Comparison comparison, final Class javaType) { final Object value = comparison.getValue(); final List values = (value == null ? NULL_VALUE : (value instanceof List list ? list : List.of(value))).stream() - // if lookup is available, replace macros ... - .map(element -> virtualPropertyReplacer != null && element instanceof String strElement - ? virtualPropertyReplacer.replace(strElement) - : element) // converts value to the correct type .map(element -> element instanceof String strElement ? convertValueIfNecessary(strElement, javaType, comparison) diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/utils/HawkbitQlToSql.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/utils/HawkbitQlToSql.java index 6d724a00c..0a0029573 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/utils/HawkbitQlToSql.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/ql/utils/HawkbitQlToSql.java @@ -17,9 +17,9 @@ import jakarta.persistence.TypedQuery; import jakarta.persistence.criteria.CriteriaBuilder; 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.RsqlUtility.RsqlToSpecBuilder; +import org.eclipse.hawkbit.repository.QueryField; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder; public class HawkbitQlToSql { @@ -31,8 +31,8 @@ public class HawkbitQlToSql { isEclipselink = entityManager.getProperties().keySet().stream().anyMatch(key -> key.startsWith("eclipselink.")); } - public & RsqlQueryField> String toSQL( - final Class domainClass, final Class fieldsClass, final String rsql, final RsqlToSpecBuilder rsqlToSpecBuilder) { + public & QueryField> String toSQL( + final Class domainClass, final Class fieldsClass, final String rsql, final SpecBuilder rsqlToSpecBuilder) { final CriteriaQuery query = createQuery(domainClass, fieldsClass, rsql, rsqlToSpecBuilder); final TypedQuery typedQuery = entityManager.createQuery(query); if (isEclipselink) { @@ -54,20 +54,20 @@ public class HawkbitQlToSql { } } - private & RsqlQueryField> CriteriaQuery createQuery( - final Class domainClass, final Class fieldsClass, final String rsql, final RsqlToSpecBuilder rsqlToSpecBuilder) { + private & QueryField> CriteriaQuery createQuery( + final Class domainClass, final Class fieldsClass, final String rsql, final SpecBuilder rsqlToSpecBuilder) { final CriteriaQuery query = entityManager.getCriteriaBuilder().createQuery(domainClass); final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - final RsqlToSpecBuilder defaultRsqlToSpecBuilder = RsqlUtility.getInstance().getRsqlToSpecBuilder(); + final SpecBuilder defaultRsqlToSpecBuilder = QLSupport.getInstance().getSpecBuilder(); if (defaultRsqlToSpecBuilder != rsqlToSpecBuilder) { - RsqlUtility.getInstance().setRsqlToSpecBuilder(rsqlToSpecBuilder); + QLSupport.getInstance().setSpecBuilder(rsqlToSpecBuilder); } try { - return query.where(RsqlUtility.getInstance(). buildRsqlSpecification(rsql, fieldsClass) + return query.where(QLSupport.getInstance(). buildSpec(rsql, fieldsClass) .toPredicate(query.from(domainClass), cb.createQuery(domainClass), cb)); } finally { if (defaultRsqlToSpecBuilder != rsqlToSpecBuilder) { - RsqlUtility.getInstance().setRsqlToSpecBuilder(defaultRsqlToSpecBuilder); + QLSupport.getInstance().setSpecBuilder(defaultRsqlToSpecBuilder); } } } diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParser.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParser.java index 49c85487a..ffe7799f2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParser.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParser.java @@ -9,8 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.rsql; -import static org.eclipse.hawkbit.repository.RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR; -import static org.eclipse.hawkbit.repository.RsqlQueryField.SUB_ATTRIBUTE_SPLIT_REGEX; +import static org.eclipse.hawkbit.repository.QueryField.SUB_ATTRIBUTE_SEPARATOR; +import static org.eclipse.hawkbit.repository.QueryField.SUB_ATTRIBUTE_SPLIT_REGEX; import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.EQ; import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GT; import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GTE; @@ -42,7 +42,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.FieldValueConverter; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.jpa.ql.Node; @@ -82,8 +82,8 @@ public class RsqlParser { return parse(rsql, (Function) null); } - public static & RsqlQueryField> Node parse(final String rsql, final Class rsqlQueryFieldType) { - return parse(rsql, rsqlQueryFieldType == null ? null : key -> resolveKey(key, rsqlQueryFieldType)); + public static & QueryField> Node parse(final String rsql, final Class queryFieldType) { + return parse(rsql, queryFieldType == null ? null : key -> resolveKey(key, queryFieldType)); } private static Node parse(final String rsql, final Function keyResolver) { @@ -97,7 +97,7 @@ public class RsqlParser { } @SuppressWarnings("java:S3776") // java:S3776 - group in single method for easier read of whole logic - private static & RsqlQueryField> Key resolveKey(final String key, final Class rsqlQueryFieldType) { + private static & QueryField> Key resolveKey(final String key, final Class rsqlQueryFieldType) { final int firstSeparatorIndex = key.indexOf(SUB_ATTRIBUTE_SEPARATOR); final String enumName = (firstSeparatorIndex == -1 ? key : key.substring(0, firstSeparatorIndex)).toUpperCase(); log.debug("Get field identifier by name {} of enum type {}", enumName, rsqlQueryFieldType); @@ -151,9 +151,7 @@ public class RsqlParser { } } - return new - - Key(attribute, RsqlVisitor.valueConverter(enumValue)); + return new Key(attribute, RsqlVisitor.valueConverter(enumValue)); } private record Key(String path, UnaryOperator converter) {} diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/AbstractRSQLVisitor.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/AbstractRSQLVisitor.java index ab72ba2a2..320fb919e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/AbstractRSQLVisitor.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/AbstractRSQLVisitor.java @@ -23,7 +23,7 @@ import cz.jirutka.rsql.parser.ast.ComparisonOperator; import cz.jirutka.rsql.parser.ast.RSQLOperators; import lombok.Value; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder; import org.springframework.util.ObjectUtils; @@ -33,7 +33,7 @@ import org.springframework.util.ObjectUtils; */ @Deprecated(forRemoval = true, since = "0.9.0") @Slf4j -public abstract class AbstractRSQLVisitor & RsqlQueryField> { +public abstract class AbstractRSQLVisitor & QueryField> { static final ComparisonOperator IS = new ComparisonOperator("=is=", "=eq="); static final ComparisonOperator NOT = new ComparisonOperator("=not=", "=ne="); @@ -56,7 +56,7 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { @SuppressWarnings("java:S1066") // java:S1066 - more readable with separate "if" statements protected QueryPath getQueryPath(final ComparisonNode node) { - final int firstSeparatorIndex = node.getSelector().indexOf(RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR); + final int firstSeparatorIndex = node.getSelector().indexOf(QueryField.SUB_ATTRIBUTE_SEPARATOR); final String enumName = (firstSeparatorIndex == -1 ? node.getSelector() : node.getSelector().substring(0, firstSeparatorIndex)).toUpperCase(); @@ -99,14 +99,14 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { private String[] getSplit(final A enumValue, final String rsqlFieldName) { if (enumValue.isMap()) { - final String[] split = rsqlFieldName.split(RsqlQueryField.SUB_ATTRIBUTE_SPLIT_REGEX, 2); + final String[] split = rsqlFieldName.split(QueryField.SUB_ATTRIBUTE_SPLIT_REGEX, 2); if (split.length != 2 || ObjectUtils.isEmpty(split[1])) { throw new RSQLParameterUnsupportedFieldException( "The syntax of the given map search parameter field {" + rsqlFieldName + "} is wrong. Syntax is: ."); } return split; } else { - return rsqlFieldName.split(RsqlQueryField.SUB_ATTRIBUTE_SPLIT_REGEX); + return rsqlFieldName.split(QueryField.SUB_ATTRIBUTE_SPLIT_REGEX); } } @@ -123,7 +123,7 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { } for (final String attribute : subEntityAttributes) { - final String[] graph = attribute.split(RsqlQueryField.SUB_ATTRIBUTE_SPLIT_REGEX); + final String[] graph = attribute.split(QueryField.SUB_ATTRIBUTE_SPLIT_REGEX); for (final String subAttribute : graph) { if (subAttribute.equalsIgnoreCase(propertyField)) { return true; @@ -158,7 +158,7 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { .filter(enumField -> enumField.getSubEntityAttributes().isEmpty()).map(enumField -> { final String enumFieldName = enumField.name().toLowerCase(); if (enumField.isMap()) { - return enumFieldName + RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR + "keyName"; + return enumFieldName + QueryField.SUB_ATTRIBUTE_SEPARATOR + "keyName"; } else { return enumFieldName; } @@ -167,7 +167,7 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { .filter(enumField -> !enumField.getSubEntityAttributes().isEmpty()).flatMap(enumField -> { final List subEntity = enumField .getSubEntityAttributes().stream().map(fieldName -> enumField.name().toLowerCase() - + RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR + fieldName) + + QueryField.SUB_ATTRIBUTE_SEPARATOR + fieldName) .toList(); return subEntity.stream(); diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitor.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitor.java index a46be46c8..efc2ed7f5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitor.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitor.java @@ -43,7 +43,7 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.math.NumberUtils; import org.eclipse.hawkbit.repository.FieldValueConverter; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; @@ -65,7 +65,7 @@ import org.springframework.util.ObjectUtils; */ @Deprecated(forRemoval = true, since = "0.6.0") @Slf4j -public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends AbstractRSQLVisitor +public class JpaQueryRsqlVisitor & QueryField, T> extends AbstractRSQLVisitor implements RSQLVisitor, String> { public static final Character LIKE_WILDCARD = '*'; diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitorG2.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitorG2.java index dfeee3710..d3fd03f06 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitorG2.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/JpaQueryRsqlVisitorG2.java @@ -41,7 +41,7 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.math.NumberUtils; import org.eclipse.hawkbit.repository.FieldValueConverter; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder; @@ -62,7 +62,7 @@ import org.springframework.util.ObjectUtils; */ @Deprecated(forRemoval = true, since = "0.9.0") @Slf4j -public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> +public class JpaQueryRsqlVisitorG2 & QueryField, T> extends AbstractRSQLVisitor implements RSQLVisitor, String> { public static final Character LIKE_WILDCARD = '*'; diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/SpecificationBuilderLegacy.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/SpecificationBuilderLegacy.java index 54b696cd9..e548a6db6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/SpecificationBuilderLegacy.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/legacy/SpecificationBuilderLegacy.java @@ -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.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G1; import java.util.List; @@ -21,10 +21,10 @@ import cz.jirutka.rsql.parser.RSQLParserException; import cz.jirutka.rsql.parser.ast.Node; import cz.jirutka.rsql.parser.ast.RSQLVisitor; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.jpa.ql.SpecificationBuilder; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; @@ -35,7 +35,7 @@ import org.springframework.util.CollectionUtils; */ @Deprecated(forRemoval = true, since = "0.9.0") @Slf4j -public class SpecificationBuilderLegacy & RsqlQueryField, T> { +public class SpecificationBuilderLegacy & QueryField, T> { private final Class rsqlQueryFieldType; private final VirtualPropertyReplacer virtualPropertyReplacer; @@ -50,14 +50,14 @@ public class SpecificationBuilderLegacy & RsqlQueryField, T> { public Specification specification(final String rsql) { return (root, query, cb) -> { - final RsqlUtility rsqlUtility = RsqlUtility.getInstance(); + final QLSupport rsqlUtility = QLSupport.getInstance(); final Node rootNode = parseRsql(rsql, rsqlUtility); query.distinct(true); final boolean ensureIgnoreCase = !rsqlUtility.isCaseInsensitiveDB() && rsqlUtility.isIgnoreCase(); final RSQLVisitor, String> jpqQueryRSQLVisitor = - rsqlUtility.getRsqlToSpecBuilder() == LEGACY_G1 + rsqlUtility.getSpecBuilder() == LEGACY_G1 ? new JpaQueryRsqlVisitor<>(root, cb, rsqlQueryFieldType, virtualPropertyReplacer, database, query, ensureIgnoreCase) : new JpaQueryRsqlVisitorG2<>(rsqlQueryFieldType, root, query, cb, database, virtualPropertyReplacer, ensureIgnoreCase); final List accept = rootNode.accept(jpqQueryRSQLVisitor); @@ -70,7 +70,7 @@ public class SpecificationBuilderLegacy & RsqlQueryField, T> { }; } - private static Node parseRsql(final String rsql, final RsqlUtility rsqlUtility) { + private static Node parseRsql(final String rsql, final QLSupport rsqlUtility) { log.debug("Parsing rsql string {}", rsql); try { return new RSQLParser(OPERATORS).parse(rsqlUtility.isCaseInsensitiveDB() || rsqlUtility.isIgnoreCase() ? rsql.toLowerCase() : rsql); diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderLegacyTest.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderLegacyTest.java index 71a9daeac..c40f3915e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderLegacyTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderLegacyTest.java @@ -9,17 +9,16 @@ */ package org.eclipse.hawkbit.repository.jpa.ql; -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 static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G1; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G2; import java.util.Arrays; 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.QueryField; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder; import org.eclipse.hawkbit.repository.jpa.rsql.legacy.SpecificationBuilderLegacy; import org.junit.jupiter.api.Test; import org.springframework.data.jpa.domain.Specification; @@ -31,13 +30,13 @@ class SpecificationBuilderLegacyTest extends SpecificationBuilderTest { private final SpecificationBuilderLegacy builder = new SpecificationBuilderLegacy<>(RootField.class, null, Database.H2); - private static void runWithRsqlToSpecBuilder(final Runnable runnable, final RsqlToSpecBuilder rsqlToSpecBuilder) { - final RsqlToSpecBuilder defaultBuilder = RsqlUtility.getInstance().getRsqlToSpecBuilder(); - RsqlUtility.getInstance().setRsqlToSpecBuilder(rsqlToSpecBuilder); + private static void runWithRsqlToSpecBuilder(final Runnable runnable, final SpecBuilder rsqlToSpecBuilder) { + final SpecBuilder defaultBuilder = QLSupport.getInstance().getSpecBuilder(); + QLSupport.getInstance().setSpecBuilder(rsqlToSpecBuilder); try { runnable.run(); } finally { - RsqlUtility.getInstance().setRsqlToSpecBuilder(defaultBuilder); + QLSupport.getInstance().setSpecBuilder(defaultBuilder); } } @@ -110,7 +109,7 @@ class SpecificationBuilderLegacyTest extends SpecificationBuilderTest { } @Getter - private enum RootField implements RsqlQueryField { + private enum RootField implements QueryField { INTVALUE("intValue"), STRVALUE("strValue"), diff --git a/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderTest.java b/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderTest.java index be2373c02..add5bbebc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa-ql/src/test/java/org/eclipse/hawkbit/repository/jpa/ql/SpecificationBuilderTest.java @@ -10,9 +10,9 @@ package org.eclipse.hawkbit.repository.jpa.ql; import static org.assertj.core.api.Assertions.assertThat; -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 static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.G3; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G1; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G2; import java.util.List; import java.util.Map; @@ -22,9 +22,9 @@ import java.util.stream.StreamSupport; import jakarta.persistence.EntityManager; import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder; import org.eclipse.hawkbit.repository.jpa.ql.utils.HawkbitQlToSql; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser; -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; @@ -51,7 +51,7 @@ class SpecificationBuilderTest { @Autowired private EntityManager entityManager; - private final SpecificationBuilder builder = new SpecificationBuilder<>(null, false, Database.H2); + private final SpecificationBuilder builder = new SpecificationBuilder<>(false, Database.H2); @Test void singularStringAttribute() { @@ -573,8 +573,8 @@ class SpecificationBuilderTest { return builder.specification(RsqlParser.parse(rsql)); } - private static RsqlUtility.RsqlToSpecBuilder getRsqlToSpecBuilder() { - return RsqlUtility.getInstance().getRsqlToSpecBuilder(); + private static SpecBuilder getRsqlToSpecBuilder() { + return QLSupport.getInstance().getSpecBuilder(); } @SpringBootConfiguration diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java index d9a61967f..543511f93 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java @@ -91,15 +91,13 @@ public class DefaultRolloutApprovalStrategy implements RolloutApprovalStrategy { // scheduler under SYSTEM user context, thus we get the // user based on the properties of initially created rollout entity if (RolloutStatus.CREATING == rollout.getStatus()) { - final String actor = rollout.getLastModifiedBy() != null ? rollout.getLastModifiedBy() - : rollout.getCreatedBy(); + final String actor = rollout.getLastModifiedBy() != null ? rollout.getLastModifiedBy() : rollout.getCreatedBy(); if (!ObjectUtils.isEmpty(actor)) { - return systemSecurityContext.runAsSystem( - () -> userAuthoritiesResolver.getUserAuthorities(rollout.getTenant(), actor)); + return systemSecurityContext.runAsSystem(() -> userAuthoritiesResolver.getUserAuthorities(rollout.getTenant(), actor)); } } return ((User) getCurrentAuthentication().getPrincipal()).getAuthorities().stream() .map(GrantedAuthority::getAuthority).toList(); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java index 223ab77c5..c8d20b912 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java @@ -67,6 +67,8 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.DefaultQueryParser; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.QueryParser; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository; @@ -86,7 +88,7 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupEvaluati import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -513,14 +515,20 @@ public class JpaRepositoryConfiguration { return new RolloutScheduler(rolloutHandler, systemManagement, systemSecurityContext, threadPoolSize, meterRegistry); } + @Bean + @ConditionalOnMissingBean + QueryParser queryParser() { + return new DefaultQueryParser(); + } + /** - * Register the {@link RsqlUtility} bean to force Spring to inject values and auto-wired fields. + * Register the {@link QLSupport} bean to force Spring to inject values and auto-wired fields. * - * @return The {@link RsqlUtility} singleton. + * @return The {@link QLSupport} singleton. */ @Bean - RsqlUtility rsqlUtility() { - return RsqlUtility.getInstance(); + QLSupport rsqlUtility() { + return QLSupport.getInstance(); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/DefaultAccessController.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/DefaultAccessController.java index 51a545a00..d7bd263b2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/DefaultAccessController.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/DefaultAccessController.java @@ -21,10 +21,10 @@ import java.util.regex.Pattern; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.ContextAware; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.jpa.ql.EntityMatcher; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.Specification; import org.springframework.security.core.GrantedAuthority; @@ -32,7 +32,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.ObjectUtils; @Slf4j -public class DefaultAccessController & RsqlQueryField, T> implements AccessController { +public class DefaultAccessController & QueryField, T> implements AccessController { private final Class rsqlQueryFieldType; private final Map> permissions = new EnumMap<>(Operation.class); @@ -69,7 +69,7 @@ public class DefaultAccessController & RsqlQueryField, T> impl scopes.size() == 1 ? scopes.get(0) // single scope : "(" + String.join(") or (", scopes) + ")") // join multiple scopes with 'or' - union - .map(rsql -> RsqlUtility.getInstance().buildRsqlSpecification(rsql, rsqlQueryFieldType)); + .map(rsql -> QLSupport.getInstance().buildSpec(rsql, rsqlQueryFieldType)); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java index f3ab09819..640669e22 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java @@ -39,7 +39,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.RepositoryManagement; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.jpa.Jpa; @@ -49,7 +49,7 @@ import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.utils.ObjectCopyUtil; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; @@ -79,7 +79,7 @@ import org.springframework.validation.annotation.Validated; @Transactional(readOnly = true) @Validated @Slf4j -abstract class AbstractJpaRepositoryManagement, R extends BaseEntityRepository, A extends Enum & RsqlQueryField> +abstract class AbstractJpaRepositoryManagement, R extends BaseEntityRepository, A extends Enum & QueryField> implements RepositoryManagement { public static final String DELETED = "deleted"; @@ -258,8 +258,8 @@ abstract class AbstractJpaRepositoryManagement> rsqlSpec(final String rsql) { return isNotDeleted() - .map(isNotDeleted -> List.of(RsqlUtility.getInstance(). buildRsqlSpecification(rsql, fieldsClass()), isNotDeleted)) - .orElseGet(() -> List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, fieldsClass()))); + .map(isNotDeleted -> List.of(QLSupport.getInstance(). buildSpec(rsql, fieldsClass()), isNotDeleted)) + .orElseGet(() -> List.of(QLSupport.getInstance().buildSpec(rsql, fieldsClass()))); } protected void checkUpdate(final U update, final T distributionSet) {} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryWithMetadataManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryWithMetadataManagement.java index 752b84364..008791eea 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryWithMetadataManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryWithMetadataManagement.java @@ -26,9 +26,8 @@ import jakarta.persistence.EntityManager; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.MetadataSupport; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; import org.eclipse.hawkbit.repository.jpa.model.WithMetadata; import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository; @@ -39,7 +38,7 @@ import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @SuppressWarnings("java:S119") // java:S119 - better self explainable -abstract class AbstractJpaRepositoryWithMetadataManagement, C, U extends Identifiable, R extends BaseEntityRepository, A extends Enum & RsqlQueryField, MV, MVI extends MV> +abstract class AbstractJpaRepositoryWithMetadataManagement, C, U extends Identifiable, R extends BaseEntityRepository, A extends Enum & QueryField, MV, MVI extends MV> extends AbstractJpaRepositoryManagement implements MetadataSupport { private final Supplier metadataValueCreator; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index bcc189039..a3d773452 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -65,7 +65,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; @@ -252,7 +252,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl assertTargetReadAllowed(controllerId); final List> specList = Arrays.asList( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class), + QLSupport.getInstance().buildSpec(rsql, ActionFields.class), ActionSpecifications.byTargetControllerId(controllerId)); return JpaManagementHelper.countBySpec(actionRepository, specList); @@ -265,7 +265,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override public long countActions(final String rsql) { - final List> specList = List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class)); + final List> specList = List.of(QLSupport.getInstance().buildSpec(rsql, ActionFields.class)); return JpaManagementHelper.countBySpec(actionRepository, specList); } @@ -288,7 +288,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override public Slice findActions(final String rsql, final Pageable pageable) { - final List> specList = List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class)); + final List> specList = List.of(QLSupport.getInstance().buildSpec(rsql, ActionFields.class)); return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, specList, pageable); } @@ -297,7 +297,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl assertTargetReadAllowed(controllerId); final List> specList = Arrays.asList( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, ActionFields.class), + QLSupport.getInstance().buildSpec(rsql, ActionFields.class), ActionSpecifications.byTargetControllerId(controllerId)); return JpaManagementHelper.findAllWithCountBySpec(actionRepository, specList, pageable); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java index 8c2d0e9ed..d0099e6ac 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; @@ -47,7 +46,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -324,7 +323,7 @@ public class JpaDistributionSetManagement return JpaManagementHelper.findAllWithCountBySpec( jpaRepository, List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetFields.class), + QLSupport.getInstance().buildSpec(rsql, DistributionSetFields.class), DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted()), pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java index c4a54890a..459ee2031 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java @@ -13,7 +13,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; import jakarta.persistence.EntityManager; @@ -40,7 +39,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; @@ -136,7 +135,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); final List> specList = Arrays.asList( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, RolloutGroupFields.class), + QLSupport.getInstance().buildSpec(rsql, RolloutGroupFields.class), (root, query, cb) -> cb.equal(root.get(JpaRolloutGroup_.rollout).get(AbstractJpaBaseEntity_.id), rolloutId)); return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, specList, pageable); @@ -194,7 +193,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); final List> specList = Arrays.asList( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), (root, query, cb) -> { final ListJoin rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup); return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(AbstractJpaBaseEntity_.id), rolloutGroupId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index fe6981872..7bd3a9112 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -66,7 +66,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; @@ -285,7 +285,7 @@ public class JpaRolloutManagement implements RolloutManagement { @Override public Page findByRsql(final String rsql, final boolean deleted, final Pageable pageable) { final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, RolloutFields.class), + QLSupport.getInstance().buildSpec(rsql, RolloutFields.class), RolloutSpecification.isDeleted(deleted, pageable.getSort())); return JpaManagementHelper.convertPage(rolloutRepository.findAll(JpaManagementHelper.combineWithAnd(specList), pageable), pageable); } @@ -293,7 +293,7 @@ public class JpaRolloutManagement implements RolloutManagement { @Override public Page findByRsqlWithDetailedStatus(final String rsql, final boolean deleted, final Pageable pageable) { final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, RolloutFields.class), + QLSupport.getInstance().buildSpec(rsql, RolloutFields.class), RolloutSpecification.isDeleted(deleted, pageable.getSort())); return appendStatusDetails(JpaManagementHelper.convertPage( rolloutRepository.findAll(JpaManagementHelper.combineWithAnd(specList), JpaRollout_.GRAPH_ROLLOUT_DS, pageable), pageable)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java index 91d104a3b..32298eae3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java @@ -36,7 +36,7 @@ import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; @@ -117,7 +117,7 @@ class JpaTargetFilterQueryManagement @Override public void verifyTargetFilterQuerySyntax(final String query) { try { - RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class); + QLSupport.getInstance().validateQuery(query, TargetFields.class, JpaTarget.class); } catch (final RSQLParserException | RSQLParameterUnsupportedFieldException e) { log.debug("The RSQL query '{}}' is invalid.", query, e); throw new RSQLParameterSyntaxException("Cannot create a Rollout with an empty target query filter!"); @@ -136,7 +136,7 @@ class JpaTargetFilterQueryManagement final List> specList = new ArrayList<>(2); specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)); if (!ObjectUtils.isEmpty(rsql)) { - specList.add(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFilterQueryFields.class)); + specList.add(QLSupport.getInstance().buildSpec(rsql, TargetFilterQueryFields.class)); } return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable); @@ -225,7 +225,7 @@ class JpaTargetFilterQueryManagement }); Optional.ofNullable(create.getQuery()).ifPresent(query -> { // validate the RSQL query syntax - RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class); + QLSupport.getInstance().validateQuery(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 Optional.ofNullable(create.getAutoAssignDistributionSet()).ifPresent(dsId -> { @@ -242,7 +242,7 @@ class JpaTargetFilterQueryManagement final JpaTargetFilterQuery targetFilterQuery = jpaRepository.getById(update.getId()); Optional.ofNullable(update.getQuery()).ifPresent(query -> { // validate the RSQL query syntax - RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class); + QLSupport.getInstance().validateQuery(query, TargetFields.class, JpaTarget.class); Optional.ofNullable(targetFilterQuery.getAutoAssignDistributionSet()).ifPresent(autoAssignDs -> { // enforce the 'max targets per auto assignment'-quota only if the query is going to change diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java index 81cd9ab96..dee01389d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java @@ -50,7 +50,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; @@ -59,7 +59,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; -import org.eclipse.hawkbit.repository.model.TargetType; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; @@ -112,11 +111,11 @@ public class JpaTargetManagement @Override public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable( final String controllerId, final long distributionSetId, final String targetFilterQuery) { - RsqlUtility.getInstance().validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class); + QLSupport.getInstance().validateQuery(targetFilterQuery, TargetFields.class, JpaTarget.class); final DistributionSet ds = distributionSetManagement.get(distributionSetId); final Long distSetTypeId = ds.getType().getId(); final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(targetFilterQuery, TargetFields.class), + QLSupport.getInstance().buildSpec(targetFilterQuery, TargetFields.class), TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId), TargetSpecifications.hasControllerId(controllerId)); @@ -157,7 +156,7 @@ public class JpaTargetManagement .findAllWithoutCount( AccessController.Operation.UPDATE, combineWithAnd(List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))), pageable) @@ -170,7 +169,7 @@ public class JpaTargetManagement return jpaRepository .findAllWithoutCount(AccessController.Operation.UPDATE, combineWithAnd(List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.isNotInRolloutGroups(groups), TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))), pageable) @@ -191,7 +190,7 @@ public class JpaTargetManagement return jpaRepository .findAllWithoutCount(AccessController.Operation.UPDATE, combineWithAnd(List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.hasNoOverridingActionsAndNotInRollout(rolloutId), TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetType.getId()))), pageable) @@ -222,7 +221,7 @@ public class JpaTargetManagement final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId); final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())); return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable); @@ -241,7 +240,7 @@ public class JpaTargetManagement final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId); final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())); return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable); @@ -258,7 +257,7 @@ public class JpaTargetManagement throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.hasTag(tagId)); return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable); @@ -267,7 +266,7 @@ public class JpaTargetManagement @Override public long countByRsqlAndCompatible(final String rsql, final Long distributionSetIdTypeId) { final List> specList = List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); return JpaManagementHelper.countBySpec(jpaRepository, specList); } @@ -286,7 +285,7 @@ public class JpaTargetManagement return jpaRepository.count( AccessController.Operation.UPDATE, combineWithAnd(List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId)))); } @@ -296,7 +295,7 @@ public class JpaTargetManagement final String rsql, final Collection groups, final DistributionSetType dsType) { return jpaRepository.count(AccessController.Operation.UPDATE, combineWithAnd(List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class), + QLSupport.getInstance().buildSpec(rsql, TargetFields.class), TargetSpecifications.isNotInRolloutGroups(groups), TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId())))); } @@ -416,7 +415,7 @@ public class JpaTargetManagement @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public void assignTargetGroupWithRsql(String group, String rsql) { - final Specification rsqlSpecification = RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class); + final Specification rsqlSpecification = QLSupport.getInstance().buildSpec(rsql, TargetFields.class); final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaUpdate criteriaUpdateQuery = cb.createCriteriaUpdate(JpaTarget.class); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java index 9a0e97f64..ea8bb1207 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java @@ -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.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G1; import java.net.URI; import java.util.ArrayList; @@ -62,7 +62,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -636,7 +636,7 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest< */ @Test void findTargetsByRsqlWithTypeAndMetadata() { - if (RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G1) { + if (QLSupport.getInstance().getSpecBuilder() == LEGACY_G1) { // legacy visitor fail with that return; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTargetFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTargetFieldTest.java index ef58fa18d..c2bd8f5b4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTargetFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTargetFieldTest.java @@ -11,8 +11,8 @@ 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.RsqlUtility.RsqlToSpecBuilder.LEGACY_G2; -import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility.RsqlToSpecBuilder.LEGACY_G1; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G2; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G1; import java.util.Arrays; import java.util.Map; @@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; +import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; @@ -177,7 +178,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 (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) { + if (QLSupport.getInstance().getSpecBuilder() != 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 @@ -191,22 +192,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 (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) { + if (QLSupport.getInstance().getSpecBuilder() != LEGACY_G1) { assertRSQLQuery( TargetFields.ATTRIBUTE.name() + ".test.dot=not=value.dot", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0); + QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 5 : 0); assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null=not=null", 1); // null check assertRSQLQuery( TargetFields.ATTRIBUTE.name() + ".test.null=not=null2", - 1 + (RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check + 1 + (QLSupport.getInstance().getSpecBuilder() == 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", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0); + QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 5 : 0); assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.null=ne=null", 1); // null check assertRSQLQuery( TargetFields.ATTRIBUTE.name() + ".test.null=ne=null2", - 1 + (RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check + 1 + (QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 5 : 0)); // value check assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.n/a=ne=null", 0); // null check } @@ -303,7 +304,7 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest { assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==noExist*", 0); assertRSQLQuery(TargetFields.METADATA.name() + ".notExist==metaValue", 0); - if (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) { + if (QLSupport.getInstance().getSpecBuilder() != 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); @@ -321,27 +322,27 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest { assertRSQLQuery(TargetFields.METADATA.name() + ".notExist!=metaValue", 0); assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey!=notExist", 2); - if (RsqlUtility.getInstance().getRsqlToSpecBuilder() != LEGACY_G1) { + if (QLSupport.getInstance().getSpecBuilder() != LEGACY_G1) { assertRSQLQuery( TargetFields.METADATA.name() + ".metaKey=not=metaValue", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 4 : 1); + QLSupport.getInstance().getSpecBuilder() == 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", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0); + QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0); assertRSQLQuery( TargetFields.METADATA.name() + ".metaKey=not=notExist", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2); + QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2); assertRSQLQuery( TargetFields.METADATA.name() + ".metaKey=ne=metaValue", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 4 : 1); + QLSupport.getInstance().getSpecBuilder() == 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", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0); + QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 1 + 5 : 0); assertRSQLQuery( TargetFields.METADATA.name() + ".metaKey=ne=notExist", - RsqlUtility.getInstance().getRsqlToSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2); + QLSupport.getInstance().getSpecBuilder() == LEGACY_G2 ? 2 + 4 : 2); } assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey=in=(metaValue,notexist)", 1); @@ -374,26 +375,26 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest { */ @Test void rsqlValidTargetFields() { - RsqlUtility.getInstance().validateRsqlFor( + QLSupport.getInstance().validateQuery( "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); - RsqlUtility.getInstance().validateRsqlFor( + QLSupport.getInstance().validateQuery( "ASSIGNEDDS.name == abcd and ASSIGNEDDS.version == 0123 and INSTALLEDDS.name == abcd and INSTALLEDDS.version == 0123", TargetFields.class, JpaTarget.class); - RsqlUtility.getInstance().validateRsqlFor( + QLSupport.getInstance().validateQuery( "ATTRIBUTE.subkey1 == test and ATTRIBUTE.subkey2 == test and METADATA.metakey1 == abcd and METADATA.metavalue2 == asdfg", TargetFields.class, JpaTarget.class); - RsqlUtility.getInstance().validateRsqlFor( + QLSupport.getInstance().validateQuery( "CREATEDAT =lt= ${NOW_TS} and LASTMODIFIEDAT =ge= ${OVERDUE_TS}", TargetFields.class, JpaTarget.class); - RsqlUtility.getInstance().validateRsqlFor( + QLSupport.getInstance().validateQuery( "ATTRIBUTE.test.dot == test and ATTRIBUTE.subkey2 == test and METADATA.test.dot == abcd and METADATA.metavalue2 == asdfg", TargetFields.class, JpaTarget.class); assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class) - .isThrownBy(() -> RsqlUtility.getInstance().validateRsqlFor("wrongfield == abcd", TargetFields.class, JpaTarget.class)); + .isThrownBy(() -> QLSupport.getInstance().validateQuery("wrongfield == abcd", TargetFields.class, JpaTarget.class)); } /** @@ -448,6 +449,6 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest { private void assertRSQLQueryThrowsException(final String rsql) { assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class) - .isThrownBy(() -> RsqlUtility.getInstance().validateRsqlFor(rsql, TargetFields.class, JpaTarget.class)); + .isThrownBy(() -> QLSupport.getInstance().validateQuery(rsql, TargetFields.class, JpaTarget.class)); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlToSqlTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlToSqlTest.java index 47c8f1677..a5ff91e11 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlToSqlTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlToSqlTest.java @@ -9,15 +9,15 @@ */ package org.eclipse.hawkbit.repository.jpa.rsql; -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.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G2; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.G3; +import static org.eclipse.hawkbit.repository.jpa.ql.QLSupport.SpecBuilder.LEGACY_G1; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.QueryField; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration; @@ -130,7 +130,7 @@ class RsqlToSqlTest { rsqlToSQL = new HawkbitQlToSql(entityManager); } - private & RsqlQueryField> void print(final Class domainClass, final Class fieldsClass, final String rsql) { + private & QueryField> void print(final Class domainClass, final Class fieldsClass, final String rsql) { System.out.println(rsql); final String legacy = rsqlToSQL.toSQL(domainClass, fieldsClass, rsql, LEGACY_G1); final String g2 = rsqlToSQL.toSQL(domainClass, fieldsClass, rsql, LEGACY_G2); @@ -143,7 +143,7 @@ class RsqlToSqlTest { } } - private & RsqlQueryField> void printFrom(final Class domainClass, final Class fieldsClass, final String rsql) { + private & QueryField> void printFrom(final Class domainClass, final Class fieldsClass, final String rsql) { System.out.println(rsql); final String legacy = rsqlToSQL.toSQL(domainClass, fieldsClass, rsql, LEGACY_G1); final String g2 = rsqlToSQL.toSQL(domainClass, fieldsClass, rsql, LEGACY_G2);