diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java
index 928467666..2897139aa 100644
--- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java
+++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtActionResourceTest.java
@@ -322,15 +322,10 @@ class MgmtActionResourceTest extends AbstractManagementApiIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds, Collections.singletonList(target));
- final String rsqlTargetControllerId = "target.controllerId==knownTargetId";
- final String rsqlTargetName = "target.name==knownTargetName";
- final String rsqlTargetUpdateStatus = "target.updateStatus==pending";
- final String rsqlTargetAddress = "target.address==http://0.0.0.0";
-
- verifyResultsByTargetPropertyFilter(target, ds, rsqlTargetControllerId);
- verifyResultsByTargetPropertyFilter(target, ds, rsqlTargetName);
- verifyResultsByTargetPropertyFilter(target, ds, rsqlTargetUpdateStatus);
- verifyResultsByTargetPropertyFilter(target, ds, rsqlTargetAddress);
+ verifyResultsByTargetPropertyFilter(target, ds, "target.controllerId==knownTargetId");
+ verifyResultsByTargetPropertyFilter(target, ds, "target.name==knownTargetName");
+ verifyResultsByTargetPropertyFilter(target, ds, "target.updateStatus==pending");
+ verifyResultsByTargetPropertyFilter(target, ds, "target.address==http://0.0.0.0");
}
@Test
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java
index b72094be1..0b9c5fd13 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.rsql;
import lombok.Getter;
import lombok.NoArgsConstructor;
+import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
/**
@@ -23,6 +24,11 @@ public final class RsqlConfigHolder {
private static final RsqlConfigHolder SINGLETON = new RsqlConfigHolder();
+ public enum RsqlToSpecBuilder {
+ LEGACY_G1, // legacy RSQL visitor
+ LEGACY_G2, // G2 RSQL visitor
+ G3 // G3 RSQL visitor - still experimental / yet default
+ }
/**
* If RSQL comparison operators shall ignore the case. If ignore case is true "x == ax" will match "x == aX"
*/
@@ -39,11 +45,12 @@ public final class RsqlConfigHolder {
private boolean caseInsensitiveDB;
/**
- * @deprecated in favour of G2 RSQL visitor. since 0.6.0
+ * @deprecated in favour fixed final visitor / spec builder of G2 RSQL visitor / G3 spec builder. since 0.6.0
*/
+ @Setter // for tests only
@Deprecated(forRemoval = true, since = "0.6.0")
- @Value("${hawkbit.rsql.legacy-rsql-visitor:false}")
- private boolean legacyRsqlVisitor;
+ @Value("${hawkbit.rsql.rsql-to-spec-builder:G3}") //
+ private RsqlToSpecBuilder rsqlToSpecBuilder;
/**
* @return The holder singleton instance.
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/Node.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/Node.java
new file mode 100644
index 000000000..cc532749e
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/Node.java
@@ -0,0 +1,211 @@
+/**
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.hawkbit.repository.jpa.rsql;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Node is always in Disjunctive Normal Form (DNF). This means:
+ *
null
* @param database database in use
* @return a specification which can be used with JPA
@@ -93,98 +93,34 @@ public final class RSQLUtility {
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
*/
public static & RsqlQueryField, T> Specification