Extract QL support in a top level module (#2808)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-11-14 14:19:36 +02:00
committed by GitHub
parent df4464406e
commit c5ea265e0f
71 changed files with 454 additions and 485 deletions

View File

@@ -1,69 +0,0 @@
# hawkBit Migration Guides
## Release 0.2
### Configuration Property changes
- `hawkbit.server.controller._` have changed to `hawkbit.server.ddi._`
- `info.build._` have changed to `hawkbit.server.build._`
- `hawkbit.server.demo._` have changed to `hawkbit.server.ui.demo._`
- `hawkbit.server.email.support` has changed to `hawkbit.server.ui.links.support`
- `hawkbit.server.email.request.account` has changed to `hawkbit.server.ui.links.requestAccount`
- `hawkbit.server.im.login.url` has changed to `hawkbit.server.ui.links.userManagement`
### REST API model changes for clients
- ENTITYPagedList classes have been removed; generic `PagedList` used instead (e.g. `PagedList<TargetRest>` instead
of `TargetPagedList`).
- ENTITYsrest classes have been removed; `List<ENTITYrest>` used instead (e.g. `List<TargetRest>` instead
of `TargetsRest`)
### Renamed api annotations
- Annotation `org.eclipse.hawkbit.rest.resource.EnableRestResources` has changed
to `org.eclipse.hawkbit.mgmt.annotation.EnableMgmtApi`
- Annotation `org.eclipse.hawkbit.ddi.resource.EnableDirectDeviceApi` has changed
to `org.eclipse.hawkbit.ddi.annotation.EnableDdiApi`
### Renamed maven modules
- Module `hawkbit-mgmt-api-client` has changed to `hawkbit-example-mgmt-simulator`
## Milestone 0.3.0M6
### Configuration Property changes
- `hawkbit.server.security.dos.maxTargetsPerManualAssignment` has changed
to `hawkbit.server.security.dos.maxTargetDistributionSetAssignmentsPerManualAssignment`
## Milestone 0.3.0M7
### Configuration Property changes
- Due to Spring Boot version upgrade (
see [spring boot 2.2 deprecations](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#deprecations-in-spring-boot-22)) `server.use-forward-headers`
has changed to `server.forward-headers-strategy`
## Upgrade from Master Branch (after 0.3.0M6) to 0.3.0M7
Due to changes in the DB migration scripts within PR [#1017](https://github.com/eclipse-hawkbit/hawkbit/pull/1017) the
Hawkbit will not start up if one of the following cases is true:
- DB2 database is used
- MSSQL database is used and the `sp_action` table is not empty
- PostgreSql database is used and the `sp_action` table is not empty
The script was fixed with PR [#1061](https://github.com/eclipse-hawkbit/hawkbit/pull/1061).
In case you upgrade from 0.3.0M6 to 0.3.0M7 there is no issue. But if you have built the Hawkbit from the master branch
between PR [#1017](https://github.com/eclipse-hawkbit/hawkbit/pull/1017) and
PR [#1061](https://github.com/eclipse-hawkbit/hawkbit/pull/1061), use PostgreSQL or MSSQL and upgrade to 0.3.0M7, it
will fail at startup with the message: `Validate failed: Migration checksum mismatch for migration version 1.12.16`
This can be fixed by adapting the schema_version table of the database. The checksum field of the entry with the version
1.12.16 has to be changed (mind the minus):
- -1684307461 for MSSQL
- -596342656 for PostgreSql
Example for MSSQL: `UPDATE schema_version SET checksum=-1684307461 WHERE version='1.12.16'`

View File

@@ -88,7 +88,7 @@ public final class MgmtTargetMapper {
.withRel(MgmtRestConstants.TARGET_V1_ATTRIBUTES).expand()); .withRel(MgmtRestConstants.TARGET_V1_ATTRIBUTES).expand());
response.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionHistory(response.getControllerId(), null, 0, response.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionHistory(response.getControllerId(), null, 0,
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE,
ActionFields.ID.getJpaEntityFieldName() + ":" + SortDirection.DESC)) ActionFields.ID.getName() + ":" + SortDirection.DESC))
.withRel(MgmtRestConstants.TARGET_V1_ACTIONS).expand()); .withRel(MgmtRestConstants.TARGET_V1_ACTIONS).expand());
response.add(linkTo(methodOn(MgmtTargetRestApi.class).getMetadata(response.getControllerId())) response.add(linkTo(methodOn(MgmtTargetRestApi.class).getMetadata(response.getControllerId()))
.withRel("metadata").expand()); .withRel("metadata").expand());
@@ -289,7 +289,7 @@ public final class MgmtTargetMapper {
result.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionStatusList(controllerId, action.getId(), 0, result.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionStatusList(controllerId, action.getId(), 0,
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE,
ActionStatusFields.ID.getJpaEntityFieldName() + ":" + SortDirection.DESC)) ActionStatusFields.ID.getName() + ":" + SortDirection.DESC))
.withRel(MgmtRestConstants.TARGET_V1_ACTION_STATUS).expand()); .withRel(MgmtRestConstants.TARGET_V1_ACTION_STATUS).expand());
final Rollout rollout = action.getRollout(); final Rollout rollout = action.getRollout();

View File

@@ -38,7 +38,7 @@ public final class PagingUtility {
public static Sort sanitizeTargetSortParam(final String sortParam) { public static Sort sanitizeTargetSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, TargetFields.CONTROLLERID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, TargetFields.CONTROLLERID.getName());
} }
return Sort.by(SortUtility.parse(TargetFields.class, sortParam)); return Sort.by(SortUtility.parse(TargetFields.class, sortParam));
} }
@@ -46,7 +46,7 @@ public final class PagingUtility {
public static Sort sanitizeTargetTypeSortParam(final String sortParam) { public static Sort sanitizeTargetTypeSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, TargetTypeFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, TargetTypeFields.ID.getName());
} }
return Sort.by(SortUtility.parse(TargetTypeFields.class, sortParam)); return Sort.by(SortUtility.parse(TargetTypeFields.class, sortParam));
} }
@@ -54,7 +54,7 @@ public final class PagingUtility {
public static Sort sanitizeTagSortParam(final String sortParam) { public static Sort sanitizeTagSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, TagFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, TagFields.ID.getName());
} }
return Sort.by(SortUtility.parse(TagFields.class, sortParam)); return Sort.by(SortUtility.parse(TagFields.class, sortParam));
} }
@@ -62,7 +62,7 @@ public final class PagingUtility {
public static Sort sanitizeTargetFilterQuerySortParam(final String sortParam) { public static Sort sanitizeTargetFilterQuerySortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, TargetFilterQueryFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, TargetFilterQueryFields.ID.getName());
} }
return Sort.by(SortUtility.parse(TargetFilterQueryFields.class, sortParam)); return Sort.by(SortUtility.parse(TargetFilterQueryFields.class, sortParam));
} }
@@ -70,7 +70,7 @@ public final class PagingUtility {
public static Sort sanitizeSoftwareModuleSortParam(final String sortParam) { public static Sort sanitizeSoftwareModuleSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, SoftwareModuleFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, SoftwareModuleFields.ID.getName());
} }
return Sort.by(SortUtility.parse(SoftwareModuleFields.class, sortParam)); return Sort.by(SortUtility.parse(SoftwareModuleFields.class, sortParam));
} }
@@ -78,7 +78,7 @@ public final class PagingUtility {
public static Sort sanitizeSoftwareModuleTypeSortParam(final String sortParam) { public static Sort sanitizeSoftwareModuleTypeSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, SoftwareModuleTypeFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, SoftwareModuleTypeFields.ID.getName());
} }
return Sort.by(SortUtility.parse(SoftwareModuleTypeFields.class, sortParam)); return Sort.by(SortUtility.parse(SoftwareModuleTypeFields.class, sortParam));
} }
@@ -86,7 +86,7 @@ public final class PagingUtility {
public static Sort sanitizeDistributionSetSortParam(final String sortParam) { public static Sort sanitizeDistributionSetSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, DistributionSetFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, DistributionSetFields.ID.getName());
} }
return Sort.by(SortUtility.parse(DistributionSetFields.class, sortParam)); return Sort.by(SortUtility.parse(DistributionSetFields.class, sortParam));
} }
@@ -94,7 +94,7 @@ public final class PagingUtility {
public static Sort sanitizeDistributionSetTypeSortParam(final String sortParam) { public static Sort sanitizeDistributionSetTypeSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, DistributionSetTypeFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, DistributionSetTypeFields.ID.getName());
} }
return Sort.by(SortUtility.parse(DistributionSetTypeFields.class, sortParam)); return Sort.by(SortUtility.parse(DistributionSetTypeFields.class, sortParam));
} }
@@ -103,7 +103,7 @@ public final class PagingUtility {
if (sortParam == null) { if (sortParam == null) {
// default sort is DESC in case of action to match behavior // default sort is DESC in case of action to match behavior
// of management UI (last entry on top) // of management UI (last entry on top)
return Sort.by(Direction.DESC, ActionFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.DESC, ActionFields.ID.getName());
} }
return Sort.by(SortUtility.parse(ActionFields.class, sortParam)); return Sort.by(SortUtility.parse(ActionFields.class, sortParam));
} }
@@ -112,7 +112,7 @@ public final class PagingUtility {
if (sortParam == null) { if (sortParam == null) {
// default sort is DESC in case of action status to match behavior // default sort is DESC in case of action status to match behavior
// of management UI (last entry on top) // of management UI (last entry on top)
return Sort.by(Direction.DESC, ActionStatusFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.DESC, ActionStatusFields.ID.getName());
} }
return Sort.by(SortUtility.parse(ActionStatusFields.class, sortParam)); return Sort.by(SortUtility.parse(ActionStatusFields.class, sortParam));
} }
@@ -120,7 +120,7 @@ public final class PagingUtility {
public static Sort sanitizeRolloutSortParam(final String sortParam) { public static Sort sanitizeRolloutSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, RolloutFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, RolloutFields.ID.getName());
} }
return Sort.by(SortUtility.parse(RolloutFields.class, sortParam)); return Sort.by(SortUtility.parse(RolloutFields.class, sortParam));
} }
@@ -128,7 +128,7 @@ public final class PagingUtility {
public static Sort sanitizeRolloutGroupSortParam(final String sortParam) { public static Sort sanitizeRolloutGroupSortParam(final String sortParam) {
if (sortParam == null) { if (sortParam == null) {
// default // default
return Sort.by(Direction.ASC, RolloutGroupFields.ID.getJpaEntityFieldName()); return Sort.by(Direction.ASC, RolloutGroupFields.ID.getName());
} }
return Sort.by(SortUtility.parse(RolloutGroupFields.class, sortParam)); return Sort.by(SortUtility.parse(RolloutGroupFields.class, sortParam));
} }

View File

@@ -18,7 +18,7 @@ import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.mgmt.rest.resource.exception.SortParameterSyntaxErrorException; 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.SortParameterUnsupportedDirectionException;
import org.eclipse.hawkbit.mgmt.rest.resource.exception.SortParameterUnsupportedFieldException; import org.eclipse.hawkbit.mgmt.rest.resource.exception.SortParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.qfields.QueryField; import org.eclipse.hawkbit.ql.QueryField;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order; import org.springframework.data.domain.Sort.Order;
@@ -79,7 +79,7 @@ public final class SortUtility {
throw new SortParameterUnsupportedDirectionException(e); throw new SortParameterUnsupportedDirectionException(e);
} }
orders.add(new Order(sortDirection, identifier.getJpaEntityFieldName())); orders.add(new Order(sortDirection, identifier.getName()));
} else { } else {
throw new SortParameterSyntaxErrorException(); throw new SortParameterSyntaxErrorException();
} }

View File

@@ -384,7 +384,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest {
assertThat(actions).hasSize(2); assertThat(actions).hasSize(2);
updateActionStatus(actions.get(0), Status.FINISHED, null, "test"); updateActionStatus(actions.get(0), Status.FINISHED, null, "test");
final PageRequest pageRequest = PageRequest.of(0, 1000, Direction.ASC, ActionFields.ID.getJpaEntityFieldName()); final PageRequest pageRequest = PageRequest.of(0, 1000, Direction.ASC, ActionFields.ID.getName());
final Action action = deploymentManagement.findActionsByTarget(knownTargetId, pageRequest).getContent().get(0); final Action action = deploymentManagement.findActionsByTarget(knownTargetId, pageRequest).getContent().get(0);
final ActionStatus status = deploymentManagement.findActionStatusByAction(action.getId(), PAGE).getContent() final ActionStatus status = deploymentManagement.findActionStatusByAction(action.getId(), PAGE).getContent()

View File

@@ -14,20 +14,14 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository</artifactId> <artifactId>hawkbit-parent</artifactId>
<version>${revision}</version> <version>${revision}</version>
</parent> </parent>
<artifactId>hawkbit-repository-jpa-ql</artifactId> <artifactId>hawkbit-ql-jpa</artifactId>
<name>hawkBit :: Query Language</name> <name>hawkBit :: Query Language :: JPA</name>
<dependencies> <dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.persistence</groupId> <groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId> <artifactId>org.eclipse.persistence.jpa</artifactId>
@@ -63,9 +57,8 @@
<!-- Test --> <!-- Test -->
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>com.h2database</groupId>
<artifactId>hawkbit-repository-test</artifactId> <artifactId>h2</artifactId>
<version>${project.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -7,18 +7,18 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.EQ; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.EQ;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GT; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.GT;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GTE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.GTE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.IN; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.IN;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LIKE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LIKE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LT; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LT;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LTE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LTE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NOT_IN; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NOT_IN;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NOT_LIKE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NOT_LIKE;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -30,7 +30,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator; import org.eclipse.hawkbit.ql.Node.Comparison.Operator;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
/** /**

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@@ -0,0 +1,44 @@
/**
* 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.ql;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
/**
* Exception used by the REST API in case of RSQL search filter query.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class QueryException extends RuntimeException {
public enum ErrorCode {
INVALID_SYNTAX,
UNSUPPORTED_FIELD,
GENERIC // an other
}
@Getter
private final ErrorCode errorCode;
public QueryException(final ErrorCode errorCode, final String message) {
this(errorCode, message, null);
}
public QueryException(final ErrorCode errorCode, final Throwable cause) {
this(errorCode, null, cause);
}
public QueryException(final ErrorCode errorCode, final String message, final Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
}

View File

@@ -7,13 +7,13 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.ql;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jakarta.validation.constraints.NotNull; import lombok.NonNull;
/** /**
* A query field interface extended by all the fields that could be used in queries. * A query field interface extended by all the fields that could be used in queries.
@@ -27,10 +27,12 @@ public interface QueryField {
String SUB_ATTRIBUTE_SPLIT_REGEX = "\\" + SUB_ATTRIBUTE_SEPARATOR; String SUB_ATTRIBUTE_SPLIT_REGEX = "\\" + SUB_ATTRIBUTE_SEPARATOR;
/** /**
* @return the string representation of the underlying persistence field name e.g. in case of sorting. * Returns the entity field name, e.g. the JPA entity field name.
*
* @return the string representation of the underlying persistence field name.
*/ */
@NotNull @NonNull
String getJpaEntityFieldName(); String getName();
/** /**
* @return all sub entities attributes. * @return all sub entities attributes.

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -22,13 +22,11 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.text.StrLookup; import org.eclipse.hawkbit.ql.EntityMatcher;
import org.eclipse.hawkbit.repository.qfields.QueryField; import org.eclipse.hawkbit.ql.Node;
import org.eclipse.hawkbit.repository.exception.QueryException; import org.eclipse.hawkbit.ql.Node.Comparison;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.ql.QueryException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
@@ -38,17 +36,16 @@ import org.springframework.core.annotation.Order;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
/** /**
* A utility class which is able to parse RSQL strings into an spring data * A utility class which is able to parse RSQL strings into an spring data {@link Specification} which then can be enhanced sql queries to
* {@link Specification} which then can be enhanced sql queries to filter * filter entities. It has out of the box support for the RSQL parser library: https://github.com/jirutka/rsql-parser
* entities. RSQL parser library: https://github.com/jirutka/rsql-parser
* *
* <ul> * <ul>
* <li>{@code Equal to : ==}</li> * <li>{@code Equal to: ==}</li>
* <li>{@code Not equal to : !=}</li> * <li>{@code Not equal to: !=}</li>
* <li>{@code Less than : =lt= or <}</li> * <li>{@code Less than: =lt= or <}</li>
* <li>{@code Less than or equal to : =le= or <=}</li> * <li>{@code Less than or equal to: =le= or <=}</li>
* <li>{@code Greater than operator : =gt= or >}</li> * <li>{@code Greater than operator: =gt= or >}</li>
* <li>{@code Greater than or equal to : =ge= or >=}</li> * <li>{@code Greater than or equal to: =ge= or >=}</li>
* </ul> * </ul>
* <p> * <p>
* Examples of RSQL expressions in both FIQL-like and alternative notation: * Examples of RSQL expressions in both FIQL-like and alternative notation:
@@ -60,15 +57,12 @@ import org.springframework.data.jpa.domain.Specification;
* <li>{@code name==targetId1 or description==plugAndPlay or updateStatus==UNKNOWN}</li> * <li>{@code name==targetId1 or description==plugAndPlay or updateStatus==UNKNOWN}</li>
* </ul> * </ul>
* <p> * <p>
* There is also a mechanism that allows to refer to known macros that can * There is also a mechanism that allows to refer to known macros that can resolved by an optional {@link StrLookup} (cp.
* resolved by an optional {@link StrLookup} (cp.
* {@link VirtualPropertyResolver}).<br> * {@link VirtualPropertyResolver}).<br>
* An example that queries for all overdue targets using the ${OVERDUE_TS} * An example that queries for all overdue targets using the ${OVERDUE_TS} placeholder introduced by {@link VirtualPropertyResolver} looks
* placeholder introduced by {@link VirtualPropertyResolver} looks like * like this:<br>
* this:<br>
* <em>lastControllerRequestAt=le=${OVERDUE_TS}</em><br> * <em>lastControllerRequestAt=le=${OVERDUE_TS}</em><br>
* It is possible to escape a macro expression by using a second '$': * It is possible to escape a macro expression by using a second '$': $${OVERDUE_TS} would prevent the ${OVERDUE_TS} token from being expanded.
* $${OVERDUE_TS} would prevent the ${OVERDUE_TS} token from being expanded.
*/ */
@Slf4j @Slf4j
@Getter @Getter
@@ -94,9 +88,8 @@ public class QLSupport implements ApplicationListener<ContextRefreshedEvent> {
private boolean caseInsensitiveDB; private boolean caseInsensitiveDB;
private QueryParser parser; private QueryParser parser;
private List<NodeTransformer> nodeTransformers; private List<NodeTransformer> nodeTransformers = List.of();
private EntityManager entityManager; private EntityManager entityManager;
private VirtualPropertyResolver virtualPropertyResolver;
/** /**
* @return The holder singleton instance. * @return The holder singleton instance.
@@ -106,7 +99,7 @@ public class QLSupport implements ApplicationListener<ContextRefreshedEvent> {
} }
@Autowired @Autowired
void setQueryParser(final QueryParser parser) { public void setQueryParser(final QueryParser parser) {
this.parser = parser; this.parser = parser;
} }
@@ -124,11 +117,6 @@ public class QLSupport implements ApplicationListener<ContextRefreshedEvent> {
this.entityManager = entityManager; this.entityManager = entityManager;
} }
@Autowired(required = false)
void setVirtualPropertyResolver(final VirtualPropertyResolver virtualPropertyResolver) {
this.virtualPropertyResolver = virtualPropertyResolver;
}
public Node parse(final String query) { public Node parse(final String query) {
return parse(query, null); return parse(query, null);
} }
@@ -144,9 +132,7 @@ public class QLSupport implements ApplicationListener<ContextRefreshedEvent> {
* @param query the rsql query to be parsed * @param query the rsql query to be parsed
* @param queryFieldType the enum class type which implements the {@link QueryField} * @param queryFieldType the enum class type which implements the {@link QueryField}
* @return a specification which can be used with JPA * @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 * @throws QueryException if the RSQL syntax is wrong or if a field in the RSQL string is used but not provided by the given {@code queryFieldType}
* given {@code fieldNameProvider}
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
*/ */
public <A extends Enum<A> & QueryField, T> Specification<T> buildSpec(final String query, final Class<A> queryFieldType) { public <A extends Enum<A> & QueryField, T> Specification<T> buildSpec(final String query, final Class<A> queryFieldType) {
return new SpecificationBuilder<T>(ignoreCase && !caseInsensitiveDB) return new SpecificationBuilder<T>(ignoreCase && !caseInsensitiveDB)
@@ -154,8 +140,7 @@ public class QLSupport implements ApplicationListener<ContextRefreshedEvent> {
} }
public <A extends Enum<A> & QueryField, T> Specification<T> buildSpec(final Node query, final Class<A> queryFieldType) { public <A extends Enum<A> & QueryField, T> Specification<T> buildSpec(final Node query, final Class<A> queryFieldType) {
return new SpecificationBuilder<T>(ignoreCase && !caseInsensitiveDB) return new SpecificationBuilder<T>(ignoreCase && !caseInsensitiveDB).specification(transform(query, queryFieldType));
.specification(transform(query, queryFieldType));
} }
@SuppressWarnings("java:S1117") // it is again ignoreCase @SuppressWarnings("java:S1117") // it is again ignoreCase

View File

@@ -7,17 +7,19 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GT; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.GT;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GTE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.GTE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.IN; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.IN;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LIKE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LIKE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LT; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LT;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LTE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LTE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NOT_IN; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NOT_IN;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NOT_LIKE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NOT_LIKE;
import static org.eclipse.hawkbit.ql.QueryException.ErrorCode.INVALID_SYNTAX;
import static org.eclipse.hawkbit.ql.QueryException.ErrorCode.UNSUPPORTED_FIELD;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -49,11 +51,11 @@ import jakarta.persistence.metamodel.SetAttribute;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.ql.Node;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.ql.Node.Comparison;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison; import org.eclipse.hawkbit.ql.Node.Comparison.Operator;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator; import org.eclipse.hawkbit.ql.Node.Logical;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Logical; import org.eclipse.hawkbit.ql.QueryException;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@@ -129,14 +131,15 @@ public class SpecificationBuilder<T> {
} }
} }
@SuppressWarnings({ "unchecked", "java:S3776" }) // java:S3776 - easier to read at one place @SuppressWarnings("java:S3776") // java:S3776 - easier to read at one place
private Predicate predicate(final Comparison comparison) { private Predicate predicate(final Comparison comparison) {
final String[] split = comparison.getKey().split("\\.", 2); // { attributeName [, sub attribute / map key] final String[] split = comparison.getKey().split("\\.", 2); // { attributeName [, sub attribute / map key]
final Attribute<? super T, ?> attribute = root.getModel().getAttribute(split[0]); final Attribute<? super T, ?> attribute = root.getModel().getAttribute(split[0]);
final Operator op = comparison.getOp(); final Operator op = comparison.getOp();
if (attribute instanceof MapAttribute<?, ?, ?>) { if (attribute instanceof MapAttribute<?, ?, ?>) {
if (split.length < 2 || ObjectUtils.isEmpty(split[1])) { if (split.length < 2 || ObjectUtils.isEmpty(split[1])) {
throw new RSQLParameterUnsupportedFieldException( throw new QueryException(
UNSUPPORTED_FIELD,
String.format("No key for the map field found. Syntax is: %s.<key name>", getPathContext(comparison))); String.format("No key for the map field found. Syntax is: %s.<key name>", getPathContext(comparison)));
} }
if (comparison.getValue() == null) { if (comparison.getValue() == null) {
@@ -144,7 +147,8 @@ public class SpecificationBuilder<T> {
return switch (op) { return switch (op) {
case EQ -> cb.isNull(toMapValuePath(pathResolver.getJoinOn(attribute, split[1]))); case EQ -> cb.isNull(toMapValuePath(pathResolver.getJoinOn(attribute, split[1])));
case NE -> cb.isNotNull(toMapValuePath(pathResolver.getJoinOn(attribute, split[1]))); case NE -> cb.isNotNull(toMapValuePath(pathResolver.getJoinOn(attribute, split[1])));
default -> throw new RSQLParameterSyntaxException( default -> throw new QueryException(
INVALID_SYNTAX,
String.format("Operator %s is not supported for map fields with value null", op)); String.format("Operator %s is not supported for map fields with value null", op));
}; };
} else { } else {
@@ -155,7 +159,8 @@ public class SpecificationBuilder<T> {
} }
} else if (attribute instanceof SetAttribute<?, ?> setAttribute) { } else if (attribute instanceof SetAttribute<?, ?> setAttribute) {
if (split.length < 2 || ObjectUtils.isEmpty(split[1])) { if (split.length < 2 || ObjectUtils.isEmpty(split[1])) {
throw new RSQLParameterUnsupportedFieldException( throw new QueryException(
UNSUPPORTED_FIELD,
String.format("No mapping key for a set field found. Syntax is: %s.<ref name>", getPathContext(comparison))); String.format("No mapping key for a set field found. Syntax is: %s.<ref name>", getPathContext(comparison)));
} }
if (isNot(op)) { if (isNot(op)) {
@@ -243,24 +248,24 @@ public class SpecificationBuilder<T> {
: element) : element)
.toList(); .toList();
if (values.isEmpty()) { if (values.isEmpty()) {
throw new RSQLParameterSyntaxException("RSQL values must not be empty", null); throw new QueryException(INVALID_SYNTAX, "RSQL values must not be empty");
} else if (values.size() == 1) { } else if (values.size() == 1) {
final Operator op = comparison.getOp(); final Operator op = comparison.getOp();
// enum, boolean or null - doesn't support >, >=, <, <= // enum, boolean or null - doesn't support >, >=, <, <=
if (!(values.get(0) instanceof String)) { if (!(values.get(0) instanceof String)) {
if (values.get(0) instanceof Number) { if (values.get(0) instanceof Number) {
if (op == LIKE || op == NOT_LIKE) { if (op == LIKE || op == NOT_LIKE) {
throw new RSQLParameterSyntaxException(op + " operator could not be applied number", null); throw new QueryException(INVALID_SYNTAX, op + " operator could not be applied number");
} }
} else if (op == GT || op == GTE || op == LT || op == LTE || op == LIKE || op == NOT_LIKE) { } else if (op == GT || op == GTE || op == LT || op == LTE || op == LIKE || op == NOT_LIKE) {
final String errorMsg = values.get(0) == null ? "null value" : "enum or boolean field"; final String errorMsg = values.get(0) == null ? "null value" : "enum or boolean field";
throw new RSQLParameterSyntaxException(op + " operator could not be applied to " + errorMsg, null); throw new QueryException(INVALID_SYNTAX, op + " operator could not be applied to " + errorMsg);
} }
} }
} else { } else {
final Operator op = comparison.getOp(); final Operator op = comparison.getOp();
if (op != IN && op != NOT_IN) { if (op != IN && op != NOT_IN) {
throw new RSQLParameterSyntaxException(op + " operator shall have exactly one value", null); throw new QueryException(INVALID_SYNTAX, op + " operator shall have exactly one value");
} }
} }
return values; return values;
@@ -276,9 +281,9 @@ public class SpecificationBuilder<T> {
if ("true".equals(value) || "false".equals(value)) { if ("true".equals(value) || "false".equals(value)) {
return Boolean.valueOf(value); return Boolean.valueOf(value);
} else { } else {
throw new RSQLParameterSyntaxException( throw new QueryException(
String.format( INVALID_SYNTAX,
"The value of %S is not well formed. Only a boolean (true or false) value will be expected", String.format("The value of %S is not well formed. Only a boolean (true or false) value will be expected",
getPathContext(comparison))); getPathContext(comparison)));
} }
} }
@@ -307,14 +312,11 @@ public class SpecificationBuilder<T> {
} else { } else {
log.debug("Provided value '{}' cannot be transformed into the correct enum type {}", value.toUpperCase(), javaType, e); log.debug("Provided value '{}' cannot be transformed into the correct enum type {}", value.toUpperCase(), javaType, e);
} }
throw new RSQLParameterUnsupportedFieldException( throw new QueryException(
String.format( UNSUPPORTED_FIELD,
"Value of %s must be one of the following: %s", String.format("Value of %s must be one of the following: %s",
getPathContext(comparison), getPathContext(comparison),
Arrays.stream(tmpEnumType.getEnumConstants()) Arrays.stream(tmpEnumType.getEnumConstants()).map(Enum::name).map(String::toLowerCase).toList()),
.map(Enum::name)
.map(String::toLowerCase)
.toList()),
e); e);
} }
} }
@@ -331,7 +333,7 @@ public class SpecificationBuilder<T> {
if (path instanceof Join<?, ?> join) { if (path instanceof Join<?, ?> join) {
return deepGetPath(join.join(subAttributeName, JoinType.LEFT), subAttributeNameSplit, startIndex); return deepGetPath(join.join(subAttributeName, JoinType.LEFT), subAttributeNameSplit, startIndex);
} else { } else {
throw new RSQLParameterSyntaxException("Unexpected sub attribute " + subAttributeName); throw new QueryException(INVALID_SYNTAX, "Unexpected sub attribute " + subAttributeName);
} }
} }
} }

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql.utils; package org.eclipse.hawkbit.ql.jpa.utils;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql.utils; package org.eclipse.hawkbit.ql.jpa.utils;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@@ -17,15 +17,16 @@ import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.CriteriaQuery;
import org.eclipse.hawkbit.repository.qfields.QueryField; import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.ql.rsql.RsqlParser;
public class HawkbitQlToSql { public class QlToSql {
private final EntityManager entityManager; private final EntityManager entityManager;
private final boolean isEclipselink; private final boolean isEclipselink;
public HawkbitQlToSql(final EntityManager entityManager) { public QlToSql(final EntityManager entityManager) {
this.entityManager = entityManager; this.entityManager = entityManager;
isEclipselink = entityManager.getProperties().keySet().stream().anyMatch(key -> key.startsWith("eclipselink.")); isEclipselink = entityManager.getProperties().keySet().stream().anyMatch(key -> key.startsWith("eclipselink."));
} }
@@ -35,7 +36,7 @@ public class HawkbitQlToSql {
final TypedQuery<?> typedQuery = entityManager.createQuery(query); final TypedQuery<?> typedQuery = entityManager.createQuery(query);
if (isEclipselink) { if (isEclipselink) {
try { try {
return (String)Class.forName("org.eclipse.hawkbit.repository.jpa.EclipselinkUtils") return (String) Class.forName("org.eclipse.hawkbit.repository.jpa.EclipselinkUtils")
.getMethod("toSql", Query.class) .getMethod("toSql", Query.class)
.invoke(null, typedQuery); .invoke(null, typedQuery);
} catch (final IllegalAccessException | NoSuchMethodException | ClassNotFoundException e) { } catch (final IllegalAccessException | NoSuchMethodException | ClassNotFoundException e) {
@@ -56,7 +57,8 @@ public class HawkbitQlToSql {
final Class<T> domainClass, final Class<A> fieldsClass, final String rsql) { final Class<T> domainClass, final Class<A> fieldsClass, final String rsql) {
final CriteriaQuery<T> query = entityManager.getCriteriaBuilder().createQuery(domainClass); final CriteriaQuery<T> query = entityManager.getCriteriaBuilder().createQuery(domainClass);
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
return query.where(QLSupport.getInstance().<A, T> buildSpec(rsql, fieldsClass) final QLSupport qlSupport = QLSupport.getInstance();
.toPredicate(query.from(domainClass), cb.createQuery(domainClass), cb)); qlSupport.setQueryParser(RsqlParser::parse);
return query.where(qlSupport.<A, T> buildSpec(rsql, fieldsClass).toPredicate(query.from(domainClass), cb.createQuery(domainClass), cb));
} }
} }

View File

@@ -7,20 +7,22 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.eclipse.hawkbit.repository.qfields.QueryField.SUB_ATTRIBUTE_SEPARATOR; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.EQ;
import static org.eclipse.hawkbit.repository.qfields.QueryField.SUB_ATTRIBUTE_SPLIT_REGEX; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.GT;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.EQ; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.GTE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GT; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.IN;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.GTE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LIKE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.IN; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LT;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LIKE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.LTE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LT; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.LTE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NOT_IN;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NE; import static org.eclipse.hawkbit.ql.Node.Comparison.Operator.NOT_LIKE;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NOT_IN; import static org.eclipse.hawkbit.ql.QueryException.ErrorCode.INVALID_SYNTAX;
import static org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison.Operator.NOT_LIKE; import static org.eclipse.hawkbit.ql.QueryException.ErrorCode.UNSUPPORTED_FIELD;
import static org.eclipse.hawkbit.ql.QueryField.SUB_ATTRIBUTE_SEPARATOR;
import static org.eclipse.hawkbit.ql.QueryField.SUB_ATTRIBUTE_SPLIT_REGEX;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -39,11 +41,10 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.qfields.QueryField; import org.eclipse.hawkbit.ql.Node;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.ql.Node.Comparison;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.ql.QueryException;
import org.eclipse.hawkbit.repository.jpa.ql.Node; import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison;
/** /**
* {@link RsqlParser} parses RSQL query stings to {@link Node} objects. Doing that it does the following: * {@link RsqlParser} parses RSQL query stings to {@link Node} objects. Doing that it does the following:
@@ -85,11 +86,9 @@ public class RsqlParser {
private static Node parse(final String rsql, final UnaryOperator<String> keyResolver) { private static Node parse(final String rsql, final UnaryOperator<String> keyResolver) {
try { try {
return RSQL_PARSER return RSQL_PARSER.parse(rsql).accept(new RsqlVisitor(keyResolver));
.parse(rsql)
.accept(new RsqlVisitor(keyResolver));
} catch (final RSQLParserException e) { } catch (final RSQLParserException e) {
throw new RSQLParameterSyntaxException(e); throw new QueryException(INVALID_SYNTAX, e);
} }
} }
@@ -103,27 +102,27 @@ public class RsqlParser {
try { try {
enumValue = Enum.valueOf(rsqlQueryFieldType, enumName); enumValue = Enum.valueOf(rsqlQueryFieldType, enumName);
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
throw new RSQLParameterUnsupportedFieldException(e); throw new QueryException(UNSUPPORTED_FIELD, e);
} }
final String attribute; final String attribute;
if (firstSeparatorIndex == -1) { // just field name without sub-attribute if (firstSeparatorIndex == -1) { // just field name without sub-attribute
if (enumValue.getSubEntityAttributes().isEmpty()) { if (enumValue.getSubEntityAttributes().isEmpty()) {
// no sub-attributes -> simple field // no sub-attributes -> simple field
attribute = enumValue.getJpaEntityFieldName(); attribute = enumValue.getName();
} else { } else {
// just enum name for a complex type (with sub-attributes), should have single (default!) sub-attribute // just enum name for a complex type (with sub-attributes), should have single (default!) sub-attribute
if (enumValue.isMap()) { if (enumValue.isMap()) {
throw new RSQLParameterUnsupportedFieldException("No key specified for a map type " + enumValue); throw new QueryException(UNSUPPORTED_FIELD, "No key specified for a map type " + enumValue);
} else { } else {
final String defaultSubEntityAttribute = enumValue.getDefaultSubEntityAttribute(); final String defaultSubEntityAttribute = enumValue.getDefaultSubEntityAttribute();
if (defaultSubEntityAttribute != null) { if (defaultSubEntityAttribute != null) {
// single sub attribute - so, treat it as a default // single sub attribute - so, treat it as a default
attribute = enumValue.getJpaEntityFieldName() + SUB_ATTRIBUTE_SEPARATOR + defaultSubEntityAttribute; attribute = enumValue.getName() + SUB_ATTRIBUTE_SEPARATOR + defaultSubEntityAttribute;
} else { } else {
throw new RSQLParameterUnsupportedFieldException( throw new QueryException(
String.format( UNSUPPORTED_FIELD,
"The given search parameter field {%s} requires one of the following sub-attributes %s", String.format("The given search parameter field {%s} requires one of the following sub-attributes %s",
key, enumValue.getSubEntityAttributes())); key, enumValue.getSubEntityAttributes()));
} }
} }
@@ -131,19 +130,19 @@ public class RsqlParser {
} else { // field name with sub-attribute } else { // field name with sub-attribute
if (enumValue.isMap()) { if (enumValue.isMap()) {
// map, the part after the enum name is the key of the map // map, the part after the enum name is the key of the map
attribute = enumValue.getJpaEntityFieldName() + SUB_ATTRIBUTE_SEPARATOR + key.substring(firstSeparatorIndex + 1); attribute = enumValue.getName() + SUB_ATTRIBUTE_SEPARATOR + key.substring(firstSeparatorIndex + 1);
} else if (enumValue.getSubEntityAttributes().isEmpty()) { } else if (enumValue.getSubEntityAttributes().isEmpty()) {
// simple type without sub-attributes, so the sub-attribute is not allowed // simple type without sub-attributes, so the sub-attribute is not allowed
throw new RSQLParameterUnsupportedFieldException("Sub-attributes not supported for simple field " + enumValue); throw new QueryException(UNSUPPORTED_FIELD, "Sub-attributes not supported for simple field " + enumValue);
} else { } else {
final String[] subAttribute = key.substring(firstSeparatorIndex + 1).split(SUB_ATTRIBUTE_SPLIT_REGEX, 2); final String[] subAttribute = key.substring(firstSeparatorIndex + 1).split(SUB_ATTRIBUTE_SPLIT_REGEX, 2);
attribute = enumValue.getJpaEntityFieldName() + SUB_ATTRIBUTE_SEPARATOR + enumValue.getSubEntityAttributes().stream() attribute = enumValue.getName() + SUB_ATTRIBUTE_SEPARATOR + enumValue.getSubEntityAttributes().stream()
.filter(attr -> attr.equalsIgnoreCase(subAttribute[0])) // case normalized .filter(attr -> attr.equalsIgnoreCase(subAttribute[0])) // case normalized
.findFirst() .findFirst()
.map(attr -> subAttribute.length == 1 ? attr : attr + key.substring(firstSeparatorIndex + 1 + attr.length())) .map(attr -> subAttribute.length == 1 ? attr : attr + key.substring(firstSeparatorIndex + 1 + attr.length()))
.orElseThrow(() -> new RSQLParameterUnsupportedFieldException( .orElseThrow(() -> new QueryException(
String.format( UNSUPPORTED_FIELD,
"The given search field {%s} has unsupported sub-attributes. Supported sub-attributes are %s", String.format("The given search field {%s} has unsupported sub-attributes. Supported sub-attributes are %s",
key, enumValue.getSubEntityAttributes()))); key, enumValue.getSubEntityAttributes())));
} }
} }

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@@ -19,8 +19,9 @@ import java.util.stream.StreamSupport;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.jpa.ql.utils.HawkbitQlToSql; import org.eclipse.hawkbit.ql.EntityMatcher;
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser; import org.eclipse.hawkbit.ql.jpa.utils.QlToSql;
import org.eclipse.hawkbit.ql.rsql.RsqlParser;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.SpringBootConfiguration;
@@ -30,9 +31,7 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
@SuppressWarnings("java:S5961") // complex check because the matter is very complex @SuppressWarnings("java:S5961") // complex check because the matter is very complex
@DataJpaTest(properties = { @DataJpaTest(properties = { "spring.jpa.database=H2" }, excludeAutoConfiguration = { FlywayAutoConfiguration.class })
"spring.jpa.database=H2"
}, excludeAutoConfiguration = { FlywayAutoConfiguration.class })
@EnableAutoConfiguration @EnableAutoConfiguration
@Slf4j @Slf4j
class SpecificationBuilderTest { class SpecificationBuilderTest {
@@ -494,10 +493,8 @@ class SpecificationBuilderTest {
try { try {
assertThat(result).containsExactlyInAnyOrder(refResult.toArray(Root[]::new)); assertThat(result).containsExactlyInAnyOrder(refResult.toArray(Root[]::new));
} catch (final AssertionError e) { } catch (final AssertionError e) {
log.error( log.error("Fail to get expected result for RSQL: {} with SQL query: {}",
"Fail to get expected result for RSQL: {} with SQL query: {}", rsql, new QlToSql(entityManager).toSQL(Root.class, null, rsql), e);
rsql, new HawkbitQlToSql(entityManager).toSQL(Root.class, null, rsql),
e);
throw e; throw e;
} }
return result; return result;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.ql; package org.eclipse.hawkbit.ql.jpa;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;

View File

@@ -22,6 +22,11 @@
<name>hawkBit :: Repository :: API</name> <name>hawkBit :: Repository :: API</name>
<dependencies> <dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-ql-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-artifact-api</artifactId> <artifactId>hawkbit-artifact-api</artifactId>

View File

@@ -1,41 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.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);
}
}

View File

@@ -21,7 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class RSQLParameterSyntaxException extends QueryException { public class RSQLParameterSyntaxException extends AbstractServerRtException {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -21,7 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class RSQLParameterUnsupportedFieldException extends QueryException { public class RSQLParameterUnsupportedFieldException extends AbstractServerRtException {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.qfields;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Sort and search fields for actions. * Sort and search fields for actions.
@@ -29,21 +30,21 @@ public enum ActionFields implements QueryField {
LASTMODIFIEDBY("lastModifiedBy"), LASTMODIFIEDBY("lastModifiedBy"),
WEIGHT("weight"), WEIGHT("weight"),
TARGET("target", TARGET("target",
TargetFields.ID.getJpaEntityFieldName(), TargetFields.NAME.getJpaEntityFieldName(), TargetFields.ID.getName(), TargetFields.NAME.getName(),
TargetFields.UPDATESTATUS.getJpaEntityFieldName(), TargetFields.IPADDRESS.getJpaEntityFieldName()), TargetFields.UPDATESTATUS.getName(), TargetFields.IPADDRESS.getName()),
DISTRIBUTIONSET("distributionSet", DISTRIBUTIONSET("distributionSet",
DistributionSetFields.ID.getJpaEntityFieldName(), DistributionSetFields.ID.getName(),
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName(), DistributionSetFields.NAME.getName(), DistributionSetFields.VERSION.getName(),
DistributionSetFields.TYPE.getJpaEntityFieldName()), DistributionSetFields.TYPE.getName()),
ROLLOUT("rollout", RolloutFields.ID.getJpaEntityFieldName(), RolloutFields.NAME.getJpaEntityFieldName()), ROLLOUT("rollout", RolloutFields.ID.getName(), RolloutFields.NAME.getName()),
ROLLOUTGROUP("rolloutGroup", RolloutGroupFields.ID.getJpaEntityFieldName(), RolloutGroupFields.NAME.getJpaEntityFieldName()), ROLLOUTGROUP("rolloutGroup", RolloutGroupFields.ID.getName(), RolloutGroupFields.NAME.getName()),
EXTERNALREF("externalRef"); EXTERNALREF("externalRef");
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
ActionFields(final String jpaEntityFieldName, final String... subEntityAttributes) { ActionFields(final String name, final String... subEntityAttributes) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = List.of(subEntityAttributes); this.subEntityAttributes = List.of(subEntityAttributes);
} }
} }

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Sort and search fields for action status. * Sort and search fields for action status.
@@ -25,9 +26,9 @@ public enum ActionStatusFields implements QueryField {
CREATEDAT("createdAt"), // same as REPORTEDAT CREATEDAT("createdAt"), // same as REPORTEDAT
CREATEDBY("createdBy"); CREATEDBY("createdBy");
private final String jpaEntityFieldName; private final String name;
ActionStatusFields(final String jpaEntityFieldName) { ActionStatusFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.qfields;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the DistributionSet model which can be used in the * Describing the fields of the DistributionSet model which can be used in the
@@ -22,9 +23,9 @@ public enum DistributionSetFields implements QueryField {
ID("id"), ID("id"),
TYPE("type", TYPE("type",
DistributionSetTypeFields.ID.getJpaEntityFieldName(), DistributionSetTypeFields.ID.getName(),
DistributionSetTypeFields.KEY.getJpaEntityFieldName(), DistributionSetTypeFields.KEY.getName(),
DistributionSetTypeFields.NAME.getJpaEntityFieldName()), DistributionSetTypeFields.NAME.getName()),
NAME("name"), NAME("name"),
DESCRIPTION("description"), DESCRIPTION("description"),
CREATEDAT("createdAt"), CREATEDAT("createdAt"),
@@ -32,22 +33,22 @@ public enum DistributionSetFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"), LASTMODIFIEDBY("lastModifiedBy"),
VERSION("version"), VERSION("version"),
MODULE("modules", SoftwareModuleFields.ID.getJpaEntityFieldName(), SoftwareModuleFields.NAME.getJpaEntityFieldName()), MODULE("modules", SoftwareModuleFields.ID.getName(), SoftwareModuleFields.NAME.getName()),
TAG("tags", "name"), TAG("tags", "name"),
METADATA("metadata"), METADATA("metadata"),
VALID("valid"); VALID("valid");
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
DistributionSetFields(final String jpaEntityFieldName, final String... subEntityAttributes) { DistributionSetFields(final String name, final String... subEntityAttributes) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = List.of(subEntityAttributes); this.subEntityAttributes = List.of(subEntityAttributes);
} }
@Override @Override
public String getDefaultSubEntityAttribute() { public String getDefaultSubEntityAttribute() {
return this == TYPE ? DistributionSetTypeFields.KEY.getJpaEntityFieldName() : QueryField.super.getDefaultSubEntityAttribute(); return this == TYPE ? DistributionSetTypeFields.KEY.getName() : QueryField.super.getDefaultSubEntityAttribute();
} }
@Override @Override

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.qfields;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the Tag model which can be used in the REST API e.g. * Describing the fields of the Tag model which can be used in the REST API e.g.
@@ -22,23 +23,23 @@ import lombok.Getter;
@Getter @Getter
public enum DistributionSetTagFields implements QueryField { public enum DistributionSetTagFields implements QueryField {
ID(TagFields.ID.getJpaEntityFieldName()), ID(TagFields.ID.getName()),
NAME(TagFields.NAME.getJpaEntityFieldName()), NAME(TagFields.NAME.getName()),
DESCRIPTION(TagFields.DESCRIPTION.getJpaEntityFieldName()), DESCRIPTION(TagFields.DESCRIPTION.getName()),
COLOUR(TagFields.COLOUR.getJpaEntityFieldName()), COLOUR(TagFields.COLOUR.getName()),
CREATEDAT("createdAt"), CREATEDAT("createdAt"),
CREATEDBY("createdBy"), CREATEDBY("createdBy"),
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"), LASTMODIFIEDBY("lastModifiedBy"),
DISTRIBUTIONSET( DISTRIBUTIONSET(
"assignedToDistributionSet", "assignedToDistributionSet",
DistributionSetFields.ID.getJpaEntityFieldName(), DistributionSetFields.NAME.getJpaEntityFieldName()); DistributionSetFields.ID.getName(), DistributionSetFields.NAME.getName());
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
DistributionSetTagFields(final String jpaEntityFieldName, final String... subEntityAttributes) { DistributionSetTagFields(final String name, final String... subEntityAttributes) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = List.of(subEntityAttributes); this.subEntityAttributes = List.of(subEntityAttributes);
} }
} }

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the DistributionSetType model which can be used in * Describing the fields of the DistributionSetType model which can be used in
@@ -27,9 +28,9 @@ public enum DistributionSetTypeFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
DistributionSetTypeFields(final String jpaEntityFieldName) { DistributionSetTypeFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.qfields;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the Rollout model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the Rollout model which can be used in the REST API e.g. for sorting etc.
@@ -29,15 +30,15 @@ public enum RolloutFields implements QueryField {
LASTMODIFIEDBY("lastModifiedBy"), LASTMODIFIEDBY("lastModifiedBy"),
DISTRIBUTIONSET( DISTRIBUTIONSET(
"distributionSet", "distributionSet",
DistributionSetFields.ID.getJpaEntityFieldName(), DistributionSetFields.ID.getName(),
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName(), DistributionSetFields.NAME.getName(), DistributionSetFields.VERSION.getName(),
DistributionSetFields.TYPE.getJpaEntityFieldName()); DistributionSetFields.TYPE.getName());
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
RolloutFields(final String jpaEntityFieldName, final String... subEntityAttributes) { RolloutFields(final String name, final String... subEntityAttributes) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = List.of(subEntityAttributes); this.subEntityAttributes = List.of(subEntityAttributes);
} }
} }

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the RolloutGroup model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the RolloutGroup model which can be used in the REST API e.g. for sorting etc.
@@ -25,9 +26,9 @@ public enum RolloutGroupFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
RolloutGroupFields(final String jpaEntityFieldName) { RolloutGroupFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.qfields;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the SoftwareModule model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the SoftwareModule model which can be used in the REST API e.g. for sorting etc.
@@ -21,9 +22,9 @@ public enum SoftwareModuleFields implements QueryField {
ID("id"), ID("id"),
TYPE("type", TYPE("type",
SoftwareModuleTypeFields.ID.getJpaEntityFieldName(), SoftwareModuleTypeFields.ID.getName(),
SoftwareModuleTypeFields.KEY.getJpaEntityFieldName(), SoftwareModuleTypeFields.KEY.getName(),
SoftwareModuleTypeFields.NAME.getJpaEntityFieldName()), SoftwareModuleTypeFields.NAME.getName()),
NAME("name"), NAME("name"),
DESCRIPTION("description"), DESCRIPTION("description"),
VERSION("version"), VERSION("version"),
@@ -33,18 +34,18 @@ public enum SoftwareModuleFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
SoftwareModuleFields(final String jpaEntityFieldName, final String... subEntityAttributes) { SoftwareModuleFields(final String name, final String... subEntityAttributes) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = List.of(subEntityAttributes); this.subEntityAttributes = List.of(subEntityAttributes);
} }
@Override @Override
public String getDefaultSubEntityAttribute() { public String getDefaultSubEntityAttribute() {
return this == TYPE ? SoftwareModuleTypeFields.KEY.getJpaEntityFieldName() : QueryField.super.getDefaultSubEntityAttribute(); return this == TYPE ? SoftwareModuleTypeFields.KEY.getName() : QueryField.super.getDefaultSubEntityAttribute();
} }
@Override @Override

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the SoftwareModuleType model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the SoftwareModuleType model which can be used in the REST API e.g. for sorting etc.
@@ -27,9 +28,9 @@ public enum SoftwareModuleTypeFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
SoftwareModuleTypeFields(final String jpaEntityFieldName) { SoftwareModuleTypeFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the Tag model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the Tag model which can be used in the REST API e.g. for sorting etc.
@@ -26,9 +27,9 @@ public enum TagFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
TagFields(final String jpaEntityFieldName) { TagFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.qfields;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the Target model which can be used in the REST API * Describing the fields of the Target model which can be used in the REST API
@@ -33,36 +34,36 @@ public enum TargetFields implements QueryField {
ATTRIBUTE("controllerAttributes"), ATTRIBUTE("controllerAttributes"),
GROUP("group"), GROUP("group"),
ASSIGNEDDS("assignedDistributionSet", ASSIGNEDDS("assignedDistributionSet",
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName()), DistributionSetFields.NAME.getName(), DistributionSetFields.VERSION.getName()),
INSTALLEDDS("installedDistributionSet", INSTALLEDDS("installedDistributionSet",
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName()), DistributionSetFields.NAME.getName(), DistributionSetFields.VERSION.getName()),
TAG("tags", TagFields.NAME.getJpaEntityFieldName()), TAG("tags", TagFields.NAME.getName()),
LASTCONTROLLERREQUESTAT("lastTargetQuery"), LASTCONTROLLERREQUESTAT("lastTargetQuery"),
METADATA("metadata"), METADATA("metadata"),
TYPE("targetType", TYPE("targetType",
TargetTypeFields.ID.getJpaEntityFieldName(), TargetTypeFields.ID.getName(),
TargetTypeFields.KEY.getJpaEntityFieldName(), TargetTypeFields.KEY.getName(),
TargetTypeFields.NAME.getJpaEntityFieldName()), TargetTypeFields.NAME.getName()),
// kept just for backward compatibility for backward compatibility // kept just for backward compatibility for backward compatibility
// could be removed only if in the systems there are no active auto assignments or rollouts (dynamic or starting) with that condition // could be removed only if in the systems there are no active auto assignments or rollouts (dynamic or starting) with that condition
// to be reconsidered if and when to be removed // to be reconsidered if and when to be removed
@Deprecated(forRemoval = true, since = "0.10.0") @Deprecated(forRemoval = true, since = "0.10.0")
TARGETTYPE("targetType", TARGETTYPE("targetType",
TargetTypeFields.ID.getJpaEntityFieldName(), TargetTypeFields.ID.getName(),
TargetTypeFields.KEY.getJpaEntityFieldName(), TargetTypeFields.KEY.getName(),
TargetTypeFields.NAME.getJpaEntityFieldName()); TargetTypeFields.NAME.getName());
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
TargetFields(final String jpaEntityFieldName, final String... subEntityAttributes) { TargetFields(final String name, final String... subEntityAttributes) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = List.of(subEntityAttributes); this.subEntityAttributes = List.of(subEntityAttributes);
} }
@Override @Override
public String getDefaultSubEntityAttribute() { public String getDefaultSubEntityAttribute() {
return this == TYPE ? TargetTypeFields.KEY.getJpaEntityFieldName() : QueryField.super.getDefaultSubEntityAttribute(); return this == TYPE ? TargetTypeFields.KEY.getName() : QueryField.super.getDefaultSubEntityAttribute();
} }
@Override @Override

View File

@@ -13,6 +13,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the Target model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the Target model which can be used in the REST API e.g. for sorting etc.
@@ -28,19 +29,19 @@ public enum TargetFilterQueryFields implements QueryField {
LASTMODIFIEDBY("lastModifiedBy"), LASTMODIFIEDBY("lastModifiedBy"),
AUTOASSIGNDISTRIBUTIONSET("autoAssignDistributionSet", "name", "version"); AUTOASSIGNDISTRIBUTIONSET("autoAssignDistributionSet", "name", "version");
private final String jpaEntityFieldName; private final String name;
private final List<String> subEntityAttributes; private final List<String> subEntityAttributes;
TargetFilterQueryFields(final String jpaEntityFieldName) { TargetFilterQueryFields(final String name) {
this(jpaEntityFieldName, Collections.emptyList()); this(name, Collections.emptyList());
} }
TargetFilterQueryFields(final String jpaEntityFieldName, final String... subEntityAttribues) { TargetFilterQueryFields(final String name, final String... subEntityAttribues) {
this(jpaEntityFieldName, List.of(subEntityAttribues)); this(name, List.of(subEntityAttribues));
} }
TargetFilterQueryFields(final String jpaEntityFieldName, final List<String> subEntityAttribues) { TargetFilterQueryFields(final String name, final List<String> subEntityAttribues) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
this.subEntityAttributes = subEntityAttribues; this.subEntityAttributes = subEntityAttribues;
} }
} }

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the Tag model which can be used in the REST API e.g. for sorting etc. * Describing the fields of the Tag model which can be used in the REST API e.g. for sorting etc.
@@ -18,18 +19,18 @@ import lombok.Getter;
@Getter @Getter
public enum TargetTagFields implements QueryField { public enum TargetTagFields implements QueryField {
ID(TagFields.ID.getJpaEntityFieldName()), ID(TagFields.ID.getName()),
NAME(TagFields.NAME.getJpaEntityFieldName()), NAME(TagFields.NAME.getName()),
DESCRIPTION(TagFields.DESCRIPTION.getJpaEntityFieldName()), DESCRIPTION(TagFields.DESCRIPTION.getName()),
COLOUR(TagFields.COLOUR.getJpaEntityFieldName()), COLOUR(TagFields.COLOUR.getName()),
CREATEDAT("createdAt"), CREATEDAT("createdAt"),
CREATEDBY("createdBy"), CREATEDBY("createdBy"),
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
TargetTagFields(final String jpaEntityFieldName) { TargetTagFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.qfields; package org.eclipse.hawkbit.repository.qfields;
import lombok.Getter; import lombok.Getter;
import org.eclipse.hawkbit.ql.QueryField;
/** /**
* Describing the fields of the TargetType model which can be used in the REST API * Describing the fields of the TargetType model which can be used in the REST API
@@ -26,9 +27,9 @@ public enum TargetTypeFields implements QueryField {
LASTMODIFIEDAT("lastModifiedAt"), LASTMODIFIEDAT("lastModifiedAt"),
LASTMODIFIEDBY("lastModifiedBy"); LASTMODIFIEDBY("lastModifiedBy");
private final String jpaEntityFieldName; private final String name;
TargetTypeFields(final String jpaEntityFieldName) { TargetTypeFields(final String name) {
this.jpaEntityFieldName = jpaEntityFieldName; this.name = name;
} }
} }

View File

@@ -16,6 +16,7 @@ import java.util.List;
import io.github.classgraph.ClassGraph; import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo; import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult; import io.github.classgraph.ScanResult;
import org.eclipse.hawkbit.ql.QueryField;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
class QueryFieldsTest { class QueryFieldsTest {

View File

@@ -18,8 +18,11 @@ import java.util.Map;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.exception.GenericSpServerException; import org.eclipse.hawkbit.exception.GenericSpServerException;
import org.eclipse.hawkbit.ql.QueryException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
@@ -66,6 +69,9 @@ public class ExceptionMapper {
* @param e the thrown and catch exception * @param e the thrown and catch exception
* @return the mapped exception * @return the mapped exception
*/ */
// java:S3776 - complex but flat
// java:S3358 - easy to read
@SuppressWarnings({ "java:S3776", "java:S3358" })
public static Exception map(final Exception e) { public static Exception map(final Exception e) {
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.trace("Handling exception {}", e.getClass().getName(), e); log.trace("Handling exception {}", e.getClass().getName(), e);
@@ -86,7 +92,8 @@ public class ExceptionMapper {
if (EXCEPTION_MAPPING.containsKey(mappedEx.getName())) { if (EXCEPTION_MAPPING.containsKey(mappedEx.getName())) {
try { try {
return (Exception) Class.forName(EXCEPTION_MAPPING.get(mappedEx.getName())).getConstructor(Throwable.class).newInstance(e); return (Exception) Class.forName(EXCEPTION_MAPPING.get(mappedEx.getName())).getConstructor(Throwable.class).newInstance(e);
} catch (final ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { } catch (final ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return e; return e;
} }
@@ -101,12 +108,21 @@ public class ExceptionMapper {
if (mappingClass != null) { if (mappingClass != null) {
try { try {
return (Exception) Class.forName(mappingClass).getConstructor(Throwable.class).newInstance(e); return (Exception) Class.forName(mappingClass).getConstructor(Throwable.class).newInstance(e);
} catch (final ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { } catch (final ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return e; return e;
} }
} }
if (e instanceof QueryException qe) {
return qe.getErrorCode() == QueryException.ErrorCode.INVALID_SYNTAX
? new RSQLParameterSyntaxException(qe.getMessage(), qe.getCause())
: (qe.getErrorCode() == QueryException.ErrorCode.UNSUPPORTED_FIELD
? new RSQLParameterUnsupportedFieldException(qe.getMessage(), qe.getCause())
: new GenericSpServerException(qe));
}
return e; return e;
} }

View File

@@ -22,10 +22,15 @@ import org.aopalliance.intercept.MethodInvocation;
import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryption; import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryption;
import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionSecretsStorage; import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionSecretsStorage;
import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionService;
import org.eclipse.hawkbit.ql.Node.Comparison;
import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.ql.jpa.QLSupport.NodeTransformer;
import org.eclipse.hawkbit.ql.jpa.QLSupport.QueryParser;
import org.eclipse.hawkbit.ql.rsql.RsqlParser;
import org.eclipse.hawkbit.repository.AutoAssignExecutor; import org.eclipse.hawkbit.repository.AutoAssignExecutor;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.PropertiesQuotaManagement; import org.eclipse.hawkbit.repository.PropertiesQuotaManagement;
import org.eclipse.hawkbit.repository.qfields.QueryField;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.RepositoryConfiguration; import org.eclipse.hawkbit.repository.RepositoryConfiguration;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
@@ -41,6 +46,8 @@ import org.eclipse.hawkbit.repository.event.ApplicationEventFilter;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManager; import org.eclipse.hawkbit.repository.event.remote.EventEntityManager;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder; import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder;
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent; import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
import org.eclipse.hawkbit.repository.jpa.aspects.ExceptionMappingAspectHandler; import org.eclipse.hawkbit.repository.jpa.aspects.ExceptionMappingAspectHandler;
import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoActionCleanup; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoActionCleanup;
@@ -58,10 +65,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder;
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
import org.eclipse.hawkbit.repository.jpa.ql.Node.Comparison;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.NodeTransformer;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport.QueryParser;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.ArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.ArtifactRepository;
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
@@ -71,7 +74,6 @@ import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository;
import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository;
import org.eclipse.hawkbit.repository.jpa.scheduler.RolloutScheduler;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAction; import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAction;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator;
@@ -79,15 +81,13 @@ 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.StartNextGroupRolloutGroupSuccessAction;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser;
import org.eclipse.hawkbit.repository.jpa.scheduler.AutoAssignScheduler; import org.eclipse.hawkbit.repository.jpa.scheduler.AutoAssignScheduler;
import org.eclipse.hawkbit.repository.jpa.scheduler.JpaAutoAssignExecutor; import org.eclipse.hawkbit.repository.jpa.scheduler.JpaAutoAssignExecutor;
import org.eclipse.hawkbit.repository.jpa.scheduler.JpaRolloutHandler; import org.eclipse.hawkbit.repository.jpa.scheduler.JpaRolloutHandler;
import org.eclipse.hawkbit.repository.jpa.scheduler.RolloutScheduler;
import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.SecurityTokenGenerator; import org.eclipse.hawkbit.security.SecurityTokenGenerator;
@@ -143,7 +143,7 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
@Import({ @Import({
RepositoryConfiguration.class, RepositoryConfiguration.class,
JpaConfiguration.class, LockProperties.class, SystemManagementCacheKeyGenerator.class, JpaConfiguration.class, LockProperties.class, SystemManagementCacheKeyGenerator.class,
DataSourceAutoConfiguration.class}) DataSourceAutoConfiguration.class })
@AutoConfigureAfter(DataSourceAutoConfiguration.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class JpaRepositoryConfiguration { public class JpaRepositoryConfiguration {
@@ -413,7 +413,8 @@ public class JpaRepositoryConfiguration {
* @return a new {@link AutoActionCleanup} bean * @return a new {@link AutoActionCleanup} bean
*/ */
@Bean @Bean
AutoCleanupScheduler.CleanupTask actionCleanup(final DeploymentManagement deploymentManagement, final TenantConfigurationManagement configManagement) { AutoCleanupScheduler.CleanupTask actionCleanup(
final DeploymentManagement deploymentManagement, final TenantConfigurationManagement configManagement) {
return new AutoActionCleanup(deploymentManagement, configManagement); return new AutoActionCleanup(deploymentManagement, configManagement);
} }

View File

@@ -14,17 +14,17 @@ import java.util.Set;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.qfields.DistributionSetFields; import org.eclipse.hawkbit.repository.qfields.DistributionSetFields;
import org.eclipse.hawkbit.repository.qfields.DistributionSetTypeFields; import org.eclipse.hawkbit.repository.qfields.DistributionSetTypeFields;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields; import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleTypeFields; import org.eclipse.hawkbit.repository.qfields.SoftwareModuleTypeFields;
import org.eclipse.hawkbit.repository.qfields.TargetFields; import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.qfields.TargetTagFields; import org.eclipse.hawkbit.repository.qfields.TargetTagFields;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
// utility class to validate authorities when ACM is enabled // utility class to validate authorities when ACM is enabled
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)

View File

@@ -18,9 +18,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.qfields.QueryField; import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;

View File

@@ -36,9 +36,10 @@ import jakarta.persistence.criteria.Root;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.qfields.QueryField;
import org.eclipse.hawkbit.repository.RepositoryManagement; import org.eclipse.hawkbit.repository.RepositoryManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
@@ -48,7 +49,6 @@ import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration;
import org.eclipse.hawkbit.repository.jpa.acm.AccessController; 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.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository; import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository;
import org.eclipse.hawkbit.utils.ObjectCopyUtil; import org.eclipse.hawkbit.utils.ObjectCopyUtil;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;

View File

@@ -24,9 +24,9 @@ import java.util.stream.Collectors;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.MetadataSupport; import org.eclipse.hawkbit.repository.MetadataSupport;
import org.eclipse.hawkbit.repository.qfields.QueryField;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity;
import org.eclipse.hawkbit.repository.jpa.model.WithMetadata; import org.eclipse.hawkbit.repository.jpa.model.WithMetadata;
@@ -46,7 +46,7 @@ abstract class AbstractJpaRepositoryWithMetadataManagement<T extends AbstractJpa
// java:S3011 - intentionally to provide option to forbid constructors // java:S3011 - intentionally to provide option to forbid constructors
// java:S1141 - better visible this way // java:S1141 - better visible this way
@SuppressWarnings({"unchecked", "java:S3011", "java:S1141"}) @SuppressWarnings({ "unchecked", "java:S3011", "java:S1141" })
protected AbstractJpaRepositoryWithMetadataManagement(final R repository, final EntityManager entityManager) { protected AbstractJpaRepositoryWithMetadataManagement(final R repository, final EntityManager entityManager) {
super(repository, entityManager); super(repository, entityManager);
try { try {
@@ -153,7 +153,7 @@ abstract class AbstractJpaRepositoryWithMetadataManagement<T extends AbstractJpa
if (Objects.equals(newValue, existingValue)) { if (Objects.equals(newValue, existingValue)) {
return false; return false;
} else { } else {
metadataValueMap.put(key, (MVI)newValue); metadataValueMap.put(key, (MVI) newValue);
return true; return true;
} }
} }

View File

@@ -46,6 +46,7 @@ import jakarta.validation.constraints.NotEmpty;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListUtils;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ConfirmationManagement;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
@@ -56,7 +57,6 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.UpdateMode; import org.eclipse.hawkbit.repository.UpdateMode;
import org.eclipse.hawkbit.repository.event.EventPublisherHolder; import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
@@ -79,7 +79,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository;
@@ -101,6 +100,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties; import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties;

View File

@@ -38,7 +38,7 @@ import jakarta.persistence.criteria.Root;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListUtils;
import org.eclipse.hawkbit.repository.qfields.ActionFields; import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryConstants;
@@ -63,7 +63,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
@@ -86,6 +85,7 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.repository.model.TargetWithActionType;
import org.eclipse.hawkbit.repository.qfields.ActionFields;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;

View File

@@ -28,7 +28,8 @@ import java.util.stream.Collectors;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.qfields.DistributionSetFields; import org.eclipse.hawkbit.ql.Node;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
@@ -44,8 +45,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.ql.Node;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository;
@@ -56,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Statistic; import org.eclipse.hawkbit.repository.model.Statistic;
import org.eclipse.hawkbit.repository.qfields.DistributionSetFields;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;

View File

@@ -22,10 +22,9 @@ import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Root;
import org.eclipse.hawkbit.repository.qfields.RolloutGroupFields; import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutGroupManagement;
import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.RolloutStatusCache;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
@@ -39,7 +38,6 @@ import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
@@ -47,6 +45,8 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.repository.qfields.RolloutGroupFields;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;

View File

@@ -32,12 +32,12 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.ContextAware;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.im.authentication.SpRole;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.RolloutApprovalStrategy; import org.eclipse.hawkbit.repository.RolloutApprovalStrategy;
import org.eclipse.hawkbit.repository.qfields.RolloutFields;
import org.eclipse.hawkbit.repository.RolloutHelper; import org.eclipse.hawkbit.repository.RolloutHelper;
import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutManagement;
import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.RolloutStatusCache;
@@ -61,7 +61,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
@@ -85,6 +84,7 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupsValidation;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.repository.qfields.RolloutFields;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.utils.ObjectCopyUtil; import org.eclipse.hawkbit.utils.ObjectCopyUtil;

View File

@@ -19,11 +19,10 @@ import jakarta.persistence.EntityManager;
import cz.jirutka.rsql.parser.RSQLParserException; import cz.jirutka.rsql.parser.RSQLParserException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.ContextAware;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.qfields.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
@@ -36,7 +35,6 @@ import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification; import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper; import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
@@ -44,6 +42,8 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.qfields.TargetFilterQueryFields;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
@@ -67,7 +67,7 @@ import org.springframework.validation.annotation.Validated;
@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-filter-management" }, matchIfMissing = true) @ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-filter-management" }, matchIfMissing = true)
class JpaTargetFilterQueryManagement class JpaTargetFilterQueryManagement
extends AbstractJpaRepositoryManagement<JpaTargetFilterQuery, TargetFilterQueryManagement.Create, TargetFilterQueryManagement.Update, TargetFilterQueryRepository, TargetFilterQueryFields> extends AbstractJpaRepositoryManagement<JpaTargetFilterQuery, TargetFilterQueryManagement.Create, TargetFilterQueryManagement.Update, TargetFilterQueryRepository, TargetFilterQueryFields>
implements TargetFilterQueryManagement<JpaTargetFilterQuery>{ implements TargetFilterQueryManagement<JpaTargetFilterQuery> {
private final TargetManagement<? extends Target> targetManagement; private final TargetManagement<? extends Target> targetManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement; private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
@@ -80,7 +80,8 @@ class JpaTargetFilterQueryManagement
protected JpaTargetFilterQueryManagement( protected JpaTargetFilterQueryManagement(
final TargetFilterQueryRepository targetFilterQueryRepository, final EntityManager entityManager, final TargetFilterQueryRepository targetFilterQueryRepository, final EntityManager entityManager,
final TargetManagement<? extends Target> targetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement, final TargetManagement<? extends Target> targetManagement,
final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement,
final RepositoryProperties repositoryProperties, final RepositoryProperties repositoryProperties,
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) { final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) {

View File

@@ -34,8 +34,8 @@ import jakarta.persistence.criteria.Root;
import jakarta.persistence.metamodel.MapAttribute; import jakarta.persistence.metamodel.MapAttribute;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
@@ -50,7 +50,6 @@ import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -58,6 +57,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -30,21 +30,21 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.qfields.TargetFields; import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException; import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException;
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValueChangeNotAllowedException; import org.eclipse.hawkbit.repository.exception.TenantConfigurationValueChangeNotAllowedException;
import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration; import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport;
import org.eclipse.hawkbit.repository.jpa.repository.TenantConfigurationRepository; import org.eclipse.hawkbit.repository.jpa.repository.TenantConfigurationRepository;
import org.eclipse.hawkbit.repository.model.PollStatus; import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAwareCacheManager; import org.eclipse.hawkbit.tenancy.TenantAwareCacheManager;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;

View File

@@ -7,11 +7,11 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.jpa.ql.Node; import org.eclipse.hawkbit.ql.Node;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
class NodeTest { class NodeTest {

View File

@@ -7,14 +7,14 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import org.eclipse.hawkbit.repository.qfields.ActionFields;
import org.eclipse.hawkbit.repository.TargetManagement.Create; import org.eclipse.hawkbit.repository.TargetManagement.Create;
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.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
@@ -22,9 +22,9 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.qfields.ActionFields;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
@@ -65,7 +65,9 @@ class RsqlActionFieldsTest extends AbstractJpaIntegrationTest {
assertRSQLQuery(ActionFields.ID.name() + "=in=(" + action.getId() + ",10000000)", 1); assertRSQLQuery(ActionFields.ID.name() + "=in=(" + action.getId() + ",10000000)", 1);
assertRSQLQuery(ActionFields.ID.name() + "=out=(" + action.getId() + ",10000000)", 10); assertRSQLQuery(ActionFields.ID.name() + "=out=(" + action.getId() + ",10000000)", 10);
}/** }
/**
* Test action by status * Test action by status
*/ */
@Test @Test
@@ -73,10 +75,10 @@ class RsqlActionFieldsTest extends AbstractJpaIntegrationTest {
assertRSQLQuery(ActionFields.ACTIVE.name() + "==" + true, 5); assertRSQLQuery(ActionFields.ACTIVE.name() + "==" + true, 5);
assertRSQLQuery(ActionFields.ACTIVE.name() + "!=" + true, 6); assertRSQLQuery(ActionFields.ACTIVE.name() + "!=" + true, 6);
assertRSQLQuery(ActionFields.ACTIVE.name() + "=in=(" + true + ")", 5); assertRSQLQuery(ActionFields.ACTIVE.name() + "=in=(" + true + ")", 5);
assertRSQLQuery(ActionFields.ACTIVE.name() + "=out=(" + true +")", 6); assertRSQLQuery(ActionFields.ACTIVE.name() + "=out=(" + true + ")", 6);
final String rsql = ActionFields.ACTIVE.name() + "==true2"; final String rsql = ActionFields.ACTIVE.name() + "==true2";
assertThatExceptionOfType(QueryException.class) assertThatExceptionOfType(RSQLParameterSyntaxException.class)
.as("RSQLParameterUnsupportedFieldException because active cannot be compared with 'true2'") .as("RSQLParameterUnsupportedFieldException because active cannot be compared with 'true2'")
.isThrownBy(() -> assertRSQLQuery(rsql, 5)); .isThrownBy(() -> assertRSQLQuery(rsql, 5));
} }
@@ -89,10 +91,10 @@ class RsqlActionFieldsTest extends AbstractJpaIntegrationTest {
assertRSQLQuery(ActionFields.STATUS.name() + "==" + Status.RUNNING, 5); assertRSQLQuery(ActionFields.STATUS.name() + "==" + Status.RUNNING, 5);
assertRSQLQuery(ActionFields.STATUS.name() + "!=" + Status.RUNNING, 6); assertRSQLQuery(ActionFields.STATUS.name() + "!=" + Status.RUNNING, 6);
assertRSQLQuery(ActionFields.STATUS.name() + "=in=(" + Status.RUNNING + ")", 5); assertRSQLQuery(ActionFields.STATUS.name() + "=in=(" + Status.RUNNING + ")", 5);
assertRSQLQuery(ActionFields.STATUS.name() + "=out=(" + Status.RUNNING +")", 6); assertRSQLQuery(ActionFields.STATUS.name() + "=out=(" + Status.RUNNING + ")", 6);
final String rsql = ActionFields.STATUS.name() + "==not_a_status"; final String rsql = ActionFields.STATUS.name() + "==not_a_status";
assertThatExceptionOfType(QueryException.class) assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
.as("RSQLParameterUnsupportedFieldException because status cannot be compared with 'not_a_status'") .as("RSQLParameterUnsupportedFieldException because status cannot be compared with 'not_a_status'")
.isThrownBy(() -> assertRSQLQuery(rsql, 5)); .isThrownBy(() -> assertRSQLQuery(rsql, 5));
} }
@@ -127,11 +129,10 @@ class RsqlActionFieldsTest extends AbstractJpaIntegrationTest {
} }
private void assertRSQLQuery(final String rsql, final long expectedEntities) { private void assertRSQLQuery(final String rsql, final long expectedEntities) {
final Slice<Action> findEntity = deploymentManagement.findActionsByTarget(rsql, target.getControllerId(), final Slice<Action> findEntity = deploymentManagement.findActionsByTarget(rsql, target.getControllerId(), PAGE);
PageRequest.of(0, 100));
final long countAllEntities = deploymentManagement.countActionsByTarget(rsql, target.getControllerId()); final long countAllEntities = deploymentManagement.countActionsByTarget(rsql, target.getControllerId());
assertThat(findEntity).isNotNull(); assertThat(findEntity).isNotNull();
assertThat(findEntity.getContent()).hasSize((int)expectedEntities); assertThat(findEntity.getContent()).hasSize((int) expectedEntities);
assertThat(countAllEntities).isEqualTo(expectedEntities); assertThat(countAllEntities).isEqualTo(expectedEntities);
} }
} }

View File

@@ -7,10 +7,10 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.hawkbit.repository.jpa.rsql.RsqlParser.parse; import static org.eclipse.hawkbit.ql.rsql.RsqlParser.parse;
import org.eclipse.hawkbit.repository.qfields.TargetFields; import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@@ -7,17 +7,17 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.qfields.RolloutFields;
import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.RolloutManagement.Create;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.qfields.RolloutFields;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -60,7 +60,8 @@ class RsqlRolloutFieldTest extends AbstractJpaIntegrationTest {
private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, final String targetFilterQuery) { private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, final String targetFilterQuery) {
return rolloutManagement.create( return rolloutManagement.create(
Create.builder() Create.builder()
.distributionSet(distributionSetManagement.find(distributionSetId).get()).name(name).targetFilterQuery(targetFilterQuery) .distributionSet(distributionSetManagement.find(distributionSetId).get()).name(name)
.targetFilterQuery(targetFilterQuery)
.build(), .build(),
amountGroups, amountGroups,
false, false,

View File

@@ -7,11 +7,10 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.qfields.RolloutGroupFields;
import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.RolloutManagement.Create;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -19,6 +18,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.qfields.RolloutGroupFields;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -98,11 +98,11 @@ class RsqlRolloutGroupFieldTest extends AbstractJpaIntegrationTest {
assertThat(countTargetsAll).isEqualTo(expectedTargets); assertThat(countTargetsAll).isEqualTo(expectedTargets);
} }
private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId, final String targetFilterQuery) {
final String targetFilterQuery) {
return rolloutManagement.create( return rolloutManagement.create(
Create.builder() Create.builder()
.distributionSet(distributionSetManagement.find(distributionSetId).get()).name(name).targetFilterQuery(targetFilterQuery) .distributionSet(distributionSetManagement.find(distributionSetId).get()).name(name)
.targetFilterQuery(targetFilterQuery)
.build(), .build(),
amountGroups, false, new RolloutGroupConditionBuilder().withDefaults() amountGroups, false, new RolloutGroupConditionBuilder().withDefaults()
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build()); .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build());

View File

@@ -7,16 +7,16 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModule.MetadataValueCreate; import org.eclipse.hawkbit.repository.model.SoftwareModule.MetadataValueCreate;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@@ -7,14 +7,14 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.Constants; import org.eclipse.hawkbit.repository.Constants;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleTypeFields;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleTypeFields;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;

View File

@@ -7,16 +7,16 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.qfields.TagFields;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.qfields.TagFields;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -15,19 +15,22 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import org.eclipse.hawkbit.repository.qfields.TargetFields; import org.eclipse.hawkbit.ql.QueryException;
import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.ql.jpa.QLSupport;
import org.eclipse.hawkbit.repository.TargetManagement.Create; import org.eclipse.hawkbit.repository.TargetManagement.Create;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.qfields.TargetTypeFields;
import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.ql.QLSupport; import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.qfields.TargetTypeFields;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -344,27 +347,26 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void rsqlValidTargetFields() { void rsqlValidTargetFields() {
final QLSupport qlSupport = QLSupport.getInstance(); validate(
qlSupport.validate(
"ID == '0123' and NAME == abcd and DESCRIPTION == absd and CREATEDAT =lt= 0123 and LASTMODIFIEDAT =gt= 0123" + "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 CONTROLLERID == 0123 and UPDATESTATUS == PENDING and IPADDRESS == 0123 and LASTCONTROLLERREQUESTAT == 0123" +
" and tag == beta", " and tag == beta",
TargetFields.class, JpaTarget.class); TargetFields.class, JpaTarget.class);
qlSupport.validate( validate(
"ASSIGNEDDS.name == abcd and ASSIGNEDDS.version == 0123 and INSTALLEDDS.name == abcd and INSTALLEDDS.version == 0123", "ASSIGNEDDS.name == abcd and ASSIGNEDDS.version == 0123 and INSTALLEDDS.name == abcd and INSTALLEDDS.version == 0123",
TargetFields.class, JpaTarget.class); TargetFields.class, JpaTarget.class);
qlSupport.validate( validate(
"ATTRIBUTE.subkey1 == test and ATTRIBUTE.subkey2 == test and METADATA.metakey1 == abcd and METADATA.metavalue2 == asdfg", "ATTRIBUTE.subkey1 == test and ATTRIBUTE.subkey2 == test and METADATA.metakey1 == abcd and METADATA.metavalue2 == asdfg",
TargetFields.class, JpaTarget.class); TargetFields.class, JpaTarget.class);
qlSupport.validate( validate(
"CREATEDAT =lt= ${NOW_TS} and LASTMODIFIEDAT =ge= ${OVERDUE_TS}", "CREATEDAT =lt= ${NOW_TS} and LASTMODIFIEDAT =ge= ${OVERDUE_TS}",
TargetFields.class, JpaTarget.class); TargetFields.class, JpaTarget.class);
qlSupport.validate( validate(
"ATTRIBUTE.test.dot == test and ATTRIBUTE.subkey2 == test and METADATA.test.dot == abcd and METADATA.metavalue2 == asdfg", "ATTRIBUTE.test.dot == test and ATTRIBUTE.subkey2 == test and METADATA.test.dot == abcd and METADATA.metavalue2 == asdfg",
TargetFields.class, JpaTarget.class); TargetFields.class, JpaTarget.class);
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class) assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
.isThrownBy(() -> qlSupport.validate("wrongfield == abcd", TargetFields.class, JpaTarget.class)); .isThrownBy(() -> validate("wrongfield == abcd", TargetFields.class, JpaTarget.class));
} }
/** /**
@@ -418,8 +420,15 @@ class RsqlTargetFieldTest extends AbstractJpaIntegrationTest {
} }
private void assertRSQLQueryThrowsException(final String rsql) { private void assertRSQLQueryThrowsException(final String rsql) {
final QLSupport qlSupport = QLSupport.getInstance();
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class) assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
.isThrownBy(() -> qlSupport.validate(rsql, TargetFields.class, JpaTarget.class)); .isThrownBy(() -> validate(rsql, TargetFields.class, JpaTarget.class));
}
private <A extends Enum<A> & QueryField> void validate(final String query, final Class<A> queryFieldType, final Class<?> jpaType) {
try {
QLSupport.getInstance().validate(query, queryFieldType, jpaType);
} catch (final QueryException e) {
throw ExceptionMapper.mapRe(e);
}
} }
} }

View File

@@ -7,17 +7,17 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.eclipse.hawkbit.repository.qfields.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.qfields.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@@ -7,20 +7,20 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import org.eclipse.hawkbit.repository.qfields.QueryField; import org.eclipse.hawkbit.ql.QueryField;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields; import org.eclipse.hawkbit.ql.jpa.utils.QlToSql;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration; import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.ql.utils.HawkbitQlToSql; import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.qfields.TargetFields;
import org.eclipse.hawkbit.repository.test.TestConfiguration; import org.eclipse.hawkbit.repository.test.TestConfiguration;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -40,7 +40,7 @@ import org.springframework.test.context.ContextConfiguration;
class RsqlToSqlTest { class RsqlToSqlTest {
private static final boolean FULL = Boolean.getBoolean("full"); private static final boolean FULL = Boolean.getBoolean("full");
private HawkbitQlToSql rsqlToSQL; private QlToSql rsqlToSQL;
@Test @Test
void printPG() { void printPG() {
@@ -106,16 +106,22 @@ class RsqlToSqlTest {
@Test @Test
void printComplex() { void printComplex() {
print(JpaTarget.class, TargetFields.class, "attribute.key1==00 and (attribute.key2==02 or attribute.key2==01)"); print(JpaTarget.class, TargetFields.class, "attribute.key1==00 and (attribute.key2==02 or attribute.key2==01)");
print(JpaTarget.class, TargetFields.class, "(attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==01"); print(JpaTarget.class, TargetFields.class,
print(JpaTarget.class, TargetFields.class, "(attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==01 and updateStatus!=pending"); "(attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==01");
print(JpaTarget.class, TargetFields.class, "((attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==03 and updateStatus!=pending)"); print(JpaTarget.class, TargetFields.class,
print(JpaTarget.class, TargetFields.class, "((attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==01 and updateStatus!=pending)"); "(attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==01 and updateStatus!=pending");
print(JpaTarget.class, TargetFields.class,
"((attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==03 and updateStatus!=pending)");
print(JpaTarget.class, TargetFields.class,
"((attribute.key1==00 or attribute.key1==01) and (attribute.key2==02 or attribute.key2==01) and attribute.key3==01 and updateStatus!=pending)");
} }
@Test @Test
void printVeryComplex() { void printVeryComplex() {
print(JpaTarget.class, TargetFields.class, "(attribute.key1==00 or attribute.key1==01) and ((attribute.key2==02 or attribute.key2==01) and (attribute.key4==02 or attribute.key5==01)) and attribute.key3==01 and updateStatus!=pending"); print(JpaTarget.class, TargetFields.class,
print(JpaTarget.class, TargetFields.class, "(attribute.key1==00 or attribute.key1==01) and ((attribute.key2==02 or attribute.key2==01) or (attribute.key4==02 or attribute.key5==01)) and attribute.key3==01 and updateStatus!=pending"); "(attribute.key1==00 or attribute.key1==01) and ((attribute.key2==02 or attribute.key2==01) and (attribute.key4==02 or attribute.key5==01)) and attribute.key3==01 and updateStatus!=pending");
print(JpaTarget.class, TargetFields.class,
"(attribute.key1==00 or attribute.key1==01) and ((attribute.key2==02 or attribute.key2==01) or (attribute.key4==02 or attribute.key5==01)) and attribute.key3==01 and updateStatus!=pending");
} }
private static String from(final String sql) { private static String from(final String sql) {
@@ -124,7 +130,7 @@ class RsqlToSqlTest {
@PersistenceContext @PersistenceContext
private void setEntityManager(final EntityManager entityManager) { private void setEntityManager(final EntityManager entityManager) {
rsqlToSQL = new HawkbitQlToSql(entityManager); rsqlToSQL = new QlToSql(entityManager);
} }
private <T, A extends Enum<A> & QueryField> void print(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql) { private <T, A extends Enum<A> & QueryField> void print(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql) {

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.ql.rsql;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -16,9 +16,9 @@ import java.util.concurrent.Callable;
import org.apache.commons.text.StringSubstitutor; import org.apache.commons.text.StringSubstitutor;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;

View File

@@ -1199,7 +1199,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void assignDistributionSetAndAddFinishedActionStatus() { void assignDistributionSetAndAddFinishedActionStatus() {
final PageRequest pageRequest = PageRequest.of(0, 100, Direction.ASC, ActionStatusFields.ID.getJpaEntityFieldName()); final PageRequest pageRequest = PageRequest.of(0, 100, Direction.ASC, ActionStatusFields.ID.getName());
final DeploymentResult deployResWithDsA = prepareComplexRepo("undep-A-T", 2, "dep-A-T", 4, 1, "dsA"); final DeploymentResult deployResWithDsA = prepareComplexRepo("undep-A-T", 2, "dep-A-T", 4, 1, "dsA");
final DeploymentResult deployResWithDsB = prepareComplexRepo("undep-B-T", 3, "dep-B-T", 5, 1, "dsB"); final DeploymentResult deployResWithDsB = prepareComplexRepo("undep-B-T", 3, "dep-B-T", 5, 1, "dsB");

View File

@@ -28,7 +28,6 @@
<module>hawkbit-repository-jpa-api</module> <module>hawkbit-repository-jpa-api</module>
<module>hawkbit-repository-jpa-eclipselink</module> <module>hawkbit-repository-jpa-eclipselink</module>
<module>hawkbit-repository-jpa-hibernate</module> <module>hawkbit-repository-jpa-hibernate</module>
<module>hawkbit-repository-jpa-ql</module>
<module>hawkbit-repository-jpa</module> <module>hawkbit-repository-jpa</module>
<module>hawkbit-repository-jpa-flyway</module> <module>hawkbit-repository-jpa-flyway</module>

View File

@@ -709,6 +709,7 @@
</profiles> </profiles>
<modules> <modules>
<module>hawkbit-ql-jpa</module>
<module>hawkbit-core</module> <module>hawkbit-core</module>
<module>hawkbit-security-core</module> <module>hawkbit-security-core</module>
<module>hawkbit-artifact</module> <module>hawkbit-artifact</module>