diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/JpaRepositoryAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/JpaRepositoryAutoConfiguration.java
index dd6ead86b..245e4d57a 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/JpaRepositoryAutoConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/JpaRepositoryAutoConfiguration.java
@@ -9,12 +9,16 @@
package org.eclipse.hawkbit.autoconfigure.repository;
import org.eclipse.hawkbit.EnableJpaRepository;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
+import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyResolver;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
- * Auto-Configuration for enabling the REST-Resources.
+ * Auto-Configuration for enabling JPA repository.
*
*/
@Configuration
@@ -22,4 +26,14 @@ import org.springframework.context.annotation.Import;
@Import({ EnableJpaRepository.class })
public class JpaRepositoryAutoConfiguration {
+ /**
+ *
+ * @return returns a VirtualPropertyReplacer
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ public VirtualPropertyReplacer virtualPropertyReplacer() {
+ return new VirtualPropertyResolver();
+ }
+
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java
new file mode 100644
index 000000000..33bafaa3c
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/FilterParams.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository;
+
+import java.util.Collection;
+
+import org.eclipse.hawkbit.repository.model.DistributionSet;
+import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
+
+/**
+ * Encapsulates a set of filters that may be specified (optionally). Properties
+ * that are not specified (e.g. null for simple properties) When
+ * applied, these filters are AND-gated.
+ *
+ */
+public class FilterParams {
+
+ private Collection filterByStatus;
+ private Boolean overdueState;
+ private String filterBySearchText;
+ private Boolean selectTargetWithNoTag;
+ private String[] filterByTagNames;
+ private Long filterByDistributionId;
+
+ /**
+ * Constructor.
+ *
+ * @param filterByDistributionId
+ * if set, a filter is added for the given
+ * {@link DistributionSet#getId()}
+ * @param filterByStatus
+ * if set, a filter is added for target states included by the
+ * collection
+ * @param overdueState
+ * if set, a filter is added for overdued devices
+ * @param filterBySearchText
+ * if set, a filter is added for the given search text
+ * @param selectTargetWithNoTag
+ * if set, tag-filtering is enabled
+ * @param filterByTagNames
+ * if tag-filtering is enabled, a filter is added for the given
+ * tag-names
+ */
+ public FilterParams(Long filterByDistributionId, Collection filterByStatus,
+ Boolean overdueState, String filterBySearchText, Boolean selectTargetWithNoTag,
+ String... filterByTagNames) {
+ this.filterByStatus = filterByStatus;
+ this.overdueState = overdueState;
+ this.filterBySearchText = filterBySearchText;
+ this.filterByDistributionId = filterByDistributionId;
+ this.selectTargetWithNoTag = selectTargetWithNoTag;
+ this.filterByTagNames = filterByTagNames;
+ }
+
+ /**
+ * Gets {@link DistributionSet#getId()} to filter the result.
+ * If set to null this filter is disabled.
+ *
+ * @return {@link DistributionSet#getId()} to filter the result
+ */
+ public Long getFilterByDistributionId() {
+ return filterByDistributionId;
+ }
+
+ /**
+ * Sets {@link DistributionSet#getId()} to filter the result.
+ *
+ * @param filterByDistributionId
+ * the distribution set id
+ */
+ public void setFilterByDistributionId(Long filterByDistributionId) {
+ this.filterByDistributionId = filterByDistributionId;
+ }
+
+ /**
+ * Gets a collection of target states to filter for.
+ * If set to null this filter is disabled.
+ *
+ * @return collection of target states to filter for
+ */
+ public Collection getFilterByStatus() {
+ return filterByStatus;
+ }
+
+ /**
+ * Sets the collection of target states to filter for.
+ *
+ * @param filterByStatus
+ * collection of target update status
+ */
+ public void setFilterByStatus(Collection filterByStatus) {
+ this.filterByStatus = filterByStatus;
+ }
+
+ /**
+ * Gets the flag for overdue filter; if set to true, the
+ * overdue filter is activated. Overdued targets a targets that did not
+ * respond during the configured intervals: poll_itvl + overdue_itvl.
+ * If set to null this filter is disabled.
+ *
+ * @return flag for overdue filter activation
+ */
+ public Boolean getOverdueState() {
+ return overdueState;
+ }
+
+ /**
+ * Sets the flag for overdue filter; if set to true, the
+ * overdue filter is activated.
+ *
+ * @param overdueState
+ * if the overdue filter should be activates
+ */
+ public void setOverdueState(Boolean overdueState) {
+ this.overdueState = overdueState;
+ }
+
+ /**
+ * Gets the search text to filter for. This is used to find targets having
+ * the text anywhere in name or description
+ * If set to null this filter is disabled.
+ *
+ * @return the search text to filter for
+ */
+ public String getFilterBySearchText() {
+ return filterBySearchText;
+ }
+
+ /**
+ * Sets the search text to filter for.
+ *
+ * @param filterBySearchText
+ * search text
+ */
+ public void setFilterBySearchText(String filterBySearchText) {
+ this.filterBySearchText = filterBySearchText;
+ }
+
+ /**
+ * Gets the flag indicating if tagging filter is used.
+ * If set to null this filter is disabled.
+ *
+ * @return the flag indicating if tagging filter is used
+ */
+ public Boolean getSelectTargetWithNoTag() {
+ return selectTargetWithNoTag;
+ }
+
+ /**
+ * Sets the flag indicating if tagging filter is used.
+ *
+ * @param selectTargetWithNoTag
+ * should the tagging filter be used?
+ */
+ public void setSelectTargetWithNoTag(Boolean selectTargetWithNoTag) {
+ this.selectTargetWithNoTag = selectTargetWithNoTag;
+ }
+
+ /**
+ * Gets the tags that are used to filter for. The activation of this filter
+ * is done by {@link #setSelectTargetWithNoTag(Boolean)}.
+ *
+ * @return the tags that are used to filter for
+ */
+ public String[] getFilterByTagNames() {
+ return filterByTagNames;
+ }
+
+ /**
+ * Sets the tags that are used to filter for.
+ *
+ * @param filterByTagNames
+ * array of tag names
+ */
+ public void setFilterByTagNames(String[] filterByTagNames) {
+ this.filterByTagNames = filterByTagNames;
+ }
+}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
index 708eb6f68..62511e9ec 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
@@ -67,7 +67,11 @@ public interface TargetManagement {
* Count {@link Target}s for all the given filter parameters.
*
* @param status
- * find targets having on of these {@link TargetUpdateStatus}s.
+ * find targets having one of these {@link TargetUpdateStatus}s.
+ * Set to null in case this is not required.
+ * @param overdueState
+ * find targets that are overdue (targets that did not respond
+ * during the configured intervals: poll_itvl + overdue_itvl).
* Set to null in case this is not required.
* @param searchText
* to find targets having the text anywhere in name or
@@ -86,7 +90,7 @@ public interface TargetManagement {
* @return the found number {@link Target}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
- Long countTargetByFilters(Collection status, String searchText,
+ Long countTargetByFilters(Collection status, Boolean overdueState, String searchText,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... tagNames);
/**
@@ -212,10 +216,12 @@ public interface TargetManagement {
*
* @param pageRequest
* the pageRequest to enhance the query for paging and sorting
- *
* @param filterByStatus
* find targets having this {@link TargetUpdateStatus}s. Set to
* null in case this is not required.
+ * @param overdueState
+ * find targets that are overdue (targets that did not respond
+ * during the configured intervals: poll_itvl + overdue_itvl).
* @param filterBySearchText
* to find targets having the text anywhere in name or
* description. Set null in case this is not
@@ -234,7 +240,7 @@ public interface TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
List findAllTargetIdsByFilters(@NotNull Pageable pageRequest,
- Collection filterByStatus, String filterBySearchText,
+ Collection filterByStatus, Boolean overdueState, String filterBySearchText,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... filterByTagNames);
/**
@@ -314,7 +320,7 @@ public interface TargetManagement {
* given {@code fieldNameProvider}
* @throws RSQLParameterSyntaxException
* if the RSQL syntax is wrong
- *
+ *
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
Page findTargetByAssignedDistributionSet(@NotNull Long distributionSetID, @NotNull String rsqlParam,
@@ -368,6 +374,9 @@ public interface TargetManagement {
* @param status
* find targets having this {@link TargetUpdateStatus}s. Set to
* null in case this is not required.
+ * @param overdueState
+ * find targets that are overdue (targets that did not respond
+ * during the configured intervals: poll_itvl + overdue_itvl).
* @param searchText
* to find targets having the text anywhere in name or
* description. Set null in case this is not
@@ -386,7 +395,7 @@ public interface TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice findTargetByFilters(@NotNull Pageable pageable, Collection status,
- String searchText, Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag,
+ Boolean overdueState, String searchText, Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag,
String... tagNames);
/**
@@ -415,7 +424,7 @@ public interface TargetManagement {
* @param pageable
* page parameter
* @return the found {@link Target}s, never {@code null}
- *
+ *
* @throws RSQLParameterUnsupportedFieldException
* if a field in the RSQL string is used but not provided by the
* given {@code fieldNameProvider}
@@ -460,9 +469,9 @@ public interface TargetManagement {
* in string notation
* @param pageable
* pagination parameter
- *
+ *
* @return the found {@link Target}s, never {@code null}
- *
+ *
* @throws RSQLParameterUnsupportedFieldException
* if a field in the RSQL string is used but not provided by the
* given {@code fieldNameProvider}
@@ -481,9 +490,9 @@ public interface TargetManagement {
* the specification for the query
* @param pageable
* pagination parameter
- *
+ *
* @return the found {@link Target}s, never {@code null}
- *
+ *
* @throws RSQLParameterUnsupportedFieldException
* if a field in the RSQL string is used but not provided by the
* given {@code fieldNameProvider}
@@ -511,33 +520,15 @@ public interface TargetManagement {
* the page request to page the result set
* @param orderByDistributionId
* {@link DistributionSet#getId()} to be ordered by
- * @param filterByDistributionId
- * {@link DistributionSet#getId()} to be filter the result. Set
- * to null in case this is not required.
- * @param filterByStatus
- * find targets having this {@link TargetUpdateStatus}s. Set to
- * null in case this is not required.
- * @param filterBySearchText
- * to find targets having the text anywhere in name or
- * description. Set null in case this is not
- * required.
- * @param installedOrAssignedDistributionSetId
- * to find targets having the {@link DistributionSet} as
- * installed or assigned. Set to null in case this
- * is not required.
- * @param filterByTagNames
- * to find targets which are having any one in this tag names.
- * Set null in case this is not required.
- * @param selectTargetWithNoTag
- * flag to select targets with no tag assigned
+ * @param filterParams
+ * the filters to apply; only filters are enabled that have
+ * non-null value; filters are AND-gated
* @return a paged result {@link Page} of the {@link Target}s in a defined
* order.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice findTargetsAllOrderByLinkedDistributionSet(@NotNull Pageable pageable,
- @NotNull Long orderByDistributionId, Long filterByDistributionId,
- Collection filterByStatus, String filterBySearchText, Boolean selectTargetWithNoTag,
- String... filterByTagNames);
+ @NotNull Long orderByDistributionId, FilterParams filterParams);
/**
* retrieves a list of {@link Target}s by their controller ID with details,
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyReplacer.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyReplacer.java
new file mode 100644
index 000000000..abdc671f7
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyReplacer.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.rsql;
+
+/**
+ * Implementations map a placeholder to the associated value.
+ *
+ * This is used in context of string replacement.
+ */
+@FunctionalInterface
+public interface VirtualPropertyReplacer {
+
+ /**
+ * Looks up a placeholders and replaces them
+ *
+ * @param input
+ * the input string in which virtual properties should be
+ * replaced
+ * @return the result of the replacement
+ */
+ String replace(String input);
+}
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/TimestampCalculator.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/TimestampCalculator.java
new file mode 100644
index 000000000..63813cf41
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/TimestampCalculator.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.jpa;
+
+import java.time.Duration;
+import java.time.Instant;
+
+import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
+import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
+import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
+import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
+
+/**
+ * Calculates non-persistent timestamps , e.g. the point a time a
+ * target is declared as overdue.
+ * Therefore tenant specific configuration may be considered.
+ *
+ */
+public final class TimestampCalculator {
+
+ private TimestampCalculator() {
+ }
+
+ /**
+ * Calculates the overdue timestamp (overdue_ts) based on the
+ * current timestamp and the intervals for polling and poll-overdue:
+ *
+ * overdue_ts = now_ts - pollingInterval -
+ * pollingOverdueInterval;
+ * pollingInterval and pollingOverdueInterval are
+ * retrieved from tenant-specific system configuration.
+ *
+ * @return overdue_ts in milliseconds since Unix epoch as long
+ * value
+ */
+ public static long calculateOverdueTimestamp() {
+ return Instant.now().toEpochMilli() - getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis()
+ - getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis();
+ }
+
+ private static Duration getDurationForKey(TenantConfigurationKey key) {
+ return DurationHelper.formattedStringToDuration(getRawStringForKey(key));
+ }
+
+ private static String getRawStringForKey(TenantConfigurationKey key) {
+ return getTenantConfigurationManagement().getConfigurationValue(key, String.class).getValue();
+ }
+
+ public static TenantConfigurationManagement getTenantConfigurationManagement() {
+ return TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement();
+ }
+}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantConfigurationManagementHolder.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantConfigurationManagementHolder.java
similarity index 100%
rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantConfigurationManagementHolder.java
rename to hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantConfigurationManagementHolder.java
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolver.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolver.java
new file mode 100644
index 000000000..14f23b5be
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolver.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.repository.jpa.rsql;
+
+import java.time.Duration;
+import java.time.Instant;
+
+import org.apache.commons.lang3.text.StrLookup;
+import org.apache.commons.lang3.text.StrSubstitutor;
+import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
+import org.eclipse.hawkbit.repository.jpa.TimestampCalculator;
+import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
+import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
+import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
+
+/**
+ * Adds macro capabilities to RSQL expressions that are used to filter for
+ * targets.
+ *
+ * Some (virtual) properties do not have a representation in the database (in
+ * general these properties are time-related, or more explicitly, they deal with
+ * time intervals).
+ * Such a virtual property needs to be calculated on Java-side before it may be
+ * used in a target filter query that is passed to the database. Therefore a
+ * placeholder is used in the RSQL expression that is expanded when the RSQL is
+ * parsed
+ *
+ * A virtual property may either be a system value like the current date (aka
+ * now_ts) or a value derived from (tenant-specific) system
+ * configuration (e.g. overdue_ts).
+ *
+ * Known values are:
+ *
+ *
now_ts: maps to system UTC time in milliseconds since Unix epoch
+ * as long value
+ *
overdue_ts: is a calculated value: overdue_ts = now_ts -
+ * pollingInterval - pollingOverdueInterval; pollingInterval and
+ * pollingOverdueInterval are retrieved from tenant-specific system
+ * configuration.
+ *
+ */
+public class VirtualPropertyResolver extends StrLookup implements VirtualPropertyReplacer {
+
+ private StrSubstitutor substitutor;
+
+ @Override
+ public String lookup(String rhs) {
+ String resolved = null;
+
+ if ("now_ts".equalsIgnoreCase(rhs)) {
+ resolved = String.valueOf(Instant.now().toEpochMilli());
+ } else if ("overdue_ts".equalsIgnoreCase(rhs)) {
+ resolved = String.valueOf(TimestampCalculator.calculateOverdueTimestamp());
+ }
+ return resolved;
+ }
+
+ @Override
+ public String replace(String input) {
+ if (substitutor == null) {
+ substitutor = new StrSubstitutor(this, StrSubstitutor.DEFAULT_PREFIX, StrSubstitutor.DEFAULT_SUFFIX,
+ StrSubstitutor.DEFAULT_ESCAPE);
+ }
+ return substitutor.replace(input);
+ }
+
+}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/pom.xml b/hawkbit-repository/hawkbit-repository-jpa/pom.xml
index 9f7a0bbb7..44f74e97c 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/pom.xml
+++ b/hawkbit-repository/hawkbit-repository-jpa/pom.xml
@@ -141,6 +141,16 @@
fest-asserttest
+
+ org.powermock
+ powermock-module-junit4
+ test
+
+
+ org.powermock
+ powermock-api-mockito
+ test
+
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
index bfd9d6fbe..5a7f98298 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
@@ -172,7 +172,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
}
/**
- *
+ *
* @return the singleton instance of the
* {@link AfterTransactionCommitExecutorHolder}
*/
@@ -234,7 +234,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaSystemManagement} bean.
- *
+ *
* @return a new {@link SystemManagement}
*/
@Bean
@@ -245,7 +245,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaReportManagement} bean.
- *
+ *
* @return a new {@link ReportManagement}
*/
@Bean
@@ -256,7 +256,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaDistributionSetManagement} bean.
- *
+ *
* @return a new {@link DistributionSetManagement}
*/
@Bean
@@ -267,7 +267,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaTenantStatsManagement} bean.
- *
+ *
* @return a new {@link TenantStatsManagement}
*/
@Bean
@@ -280,7 +280,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaTenantConfigurationManagement} bean.
- *
+ *
* @return a new {@link TenantConfigurationManagement}
*/
@Bean
@@ -291,7 +291,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaTenantConfigurationManagement} bean.
- *
+ *
* @return a new {@link TenantConfigurationManagement}
*/
@Bean
@@ -302,7 +302,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaTargetFilterQueryManagement} bean.
- *
+ *
* @return a new {@link TargetFilterQueryManagement}
*/
@Bean
@@ -313,7 +313,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaTagManagement} bean.
- *
+ *
* @return a new {@link TagManagement}
*/
@Bean
@@ -324,7 +324,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaSoftwareManagement} bean.
- *
+ *
* @return a new {@link SoftwareManagement}
*/
@Bean
@@ -335,7 +335,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaRolloutManagement} bean.
- *
+ *
* @return a new {@link RolloutManagement}
*/
@Bean
@@ -346,7 +346,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaRolloutGroupManagement} bean.
- *
+ *
* @return a new {@link RolloutGroupManagement}
*/
@Bean
@@ -357,7 +357,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaDeploymentManagement} bean.
- *
+ *
* @return a new {@link DeploymentManagement}
*/
@Bean
@@ -368,7 +368,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaControllerManagement} bean.
- *
+ *
* @return a new {@link ControllerManagement}
*/
@Bean
@@ -379,7 +379,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaArtifactManagement} bean.
- *
+ *
* @return a new {@link ArtifactManagement}
*/
@@ -391,7 +391,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
/**
* {@link JpaEntityFactory} bean.
- *
+ *
* @return a new {@link EntityFactory}
*/
@Bean
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java
index a3fb2c49e..9e8b12b86 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java
@@ -54,6 +54,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
@@ -135,6 +136,9 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@Autowired
private SystemSecurityContext systemSecurityContext;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
@Modifying
@@ -607,8 +611,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
return convertAcPage(actions, pageable);
}
- private static Specification createSpecificationFor(final Target target, final String rsqlParam) {
- final Specification spec = RSQLUtility.parse(rsqlParam, ActionFields.class);
+ private Specification createSpecificationFor(final Target target, final String rsqlParam) {
+ final Specification spec = RSQLUtility.parse(rsqlParam, ActionFields.class, virtualPropertyReplacer);
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
cb.equal(root.get(JpaAction_.target), target));
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java
index e9d3accf0..17f26b801 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java
@@ -42,6 +42,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
@@ -110,6 +111,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Autowired
private TenantAware tenantAware;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
@@ -286,7 +290,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override
public Page findDistributionSetTypesAll(final String rsqlParam, final Pageable pageable) {
final Specification spec = RSQLUtility.parse(rsqlParam,
- DistributionSetTypeFields.class);
+ DistributionSetTypeFields.class, virtualPropertyReplacer);
return convertDsTPage(distributionSetTypeRepository.findAll(spec, pageable));
}
@@ -352,7 +356,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public Page findDistributionSetsAll(final String rsqlParam, final Pageable pageReq,
final Boolean deleted) {
- final Specification spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class,
+ virtualPropertyReplacer);
final List> specList = new ArrayList<>(2);
if (deleted != null) {
@@ -528,7 +533,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
/**
* Method to get the latest distribution set based on ds ID after the
* metadata changes for that distribution set.
- *
+ *
* @param distributionSet
* Distribution set
*/
@@ -564,7 +569,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
final String rsqlParam, final Pageable pageable) {
final Specification spec = RSQLUtility.parse(rsqlParam,
- DistributionSetMetadataFields.class);
+ DistributionSetMetadataFields.class, virtualPropertyReplacer);
return convertMdPage(
distributionSetMetadataRepository
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java
index eba63b6c6..382b8fab4 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java
@@ -33,6 +33,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup_;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
@@ -70,6 +71,9 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
@Autowired
private EntityManager entityManager;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
public RolloutGroup findRolloutGroupById(final Long rolloutGroupId) {
return rolloutGroupRepository.findOne(rolloutGroupId);
@@ -92,7 +96,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
public Page findRolloutGroupsAll(final Rollout rollout, final String rsqlParam,
final Pageable pageable) {
- final Specification specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class);
+ final Specification specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class,
+ virtualPropertyReplacer);
return convertPage(
rolloutGroupRepository
@@ -145,7 +150,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
public Page findRolloutGroupTargets(final RolloutGroup rolloutGroup, final String rsqlParam,
final Pageable pageable) {
- final Specification rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class);
+ final Specification rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class,
+ virtualPropertyReplacer);
return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> {
final ListJoin rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java
index 1cb763f3a..3845a0c5a 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java
@@ -32,6 +32,7 @@ import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -114,6 +115,9 @@ public class JpaRolloutManagement implements RolloutManagement {
@Autowired
private CacheWriteNotify cacheWriteNotify;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Autowired
@Qualifier("asyncExecutor")
private Executor executor;
@@ -150,7 +154,8 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override
public Page findAllWithDetailedStatusByPredicate(final String rsqlParam, final Pageable pageable) {
- final Specification specification = RSQLUtility.parse(rsqlParam, RolloutFields.class);
+ final Specification specification = RSQLUtility.parse(rsqlParam, RolloutFields.class,
+ virtualPropertyReplacer);
final Page findAll = rolloutRepository.findAll(specification, pageable);
setRolloutStatusDetails(findAll);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java
index 26ff05cf8..a20e17f1d 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java
@@ -45,6 +45,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_;
import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule;
@@ -106,6 +107,9 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Autowired
private ArtifactManagement artifactManagement;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
@Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
@@ -312,7 +316,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override
public Page findSoftwareModulesByPredicate(final String rsqlParam, final Pageable pageable) {
- final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class,
+ virtualPropertyReplacer);
return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable);
}
@@ -320,7 +325,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override
public Page findSoftwareModuleTypesAll(final String rsqlParam, final Pageable pageable) {
- final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class,
+ virtualPropertyReplacer);
return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable);
}
@@ -606,7 +612,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
final String rsqlParam, final Pageable pageable) {
final Specification spec = RSQLUtility.parse(rsqlParam,
- SoftwareModuleMetadataFields.class);
+ SoftwareModuleMetadataFields.class, virtualPropertyReplacer);
return convertSmMdPage(
softwareModuleMetadataRepository
.findAll(
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java
index 971b5a59f..7dd292645 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java
@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.tenancy.TenantAware;
@@ -74,6 +75,9 @@ public class JpaTagManagement implements TagManagement {
@Autowired
private AfterTransactionCommitExecutor afterCommit;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
public TargetTag findTargetTag(final String name) {
return targetTagRepository.findByNameEquals(name);
@@ -145,7 +149,7 @@ public class JpaTagManagement implements TagManagement {
@Override
public Page findAllTargetTags(final String rsqlParam, final Pageable pageable) {
- final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class, virtualPropertyReplacer);
return convertTPage(targetTagRepository.findAll(spec, pageable), pageable);
}
@@ -276,7 +280,8 @@ public class JpaTagManagement implements TagManagement {
@Override
public Page findAllDistributionSetTags(final String rsqlParam, final Pageable pageable) {
- final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class,
+ virtualPropertyReplacer);
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable);
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java
index ab26ed60f..58ea2bde3 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java
@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -49,6 +50,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
@Autowired
private TargetFilterQueryRepository targetFilterQueryRepository;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
@Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
@@ -95,7 +99,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
public Page findTargetFilterQueryByFilter(@NotNull Pageable pageable, String rsqlFilter) {
List> specList = Collections.emptyList();
if (!Strings.isNullOrEmpty(rsqlFilter)) {
- specList = Collections.singletonList(RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class));
+ specList = Collections.singletonList(
+ RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer));
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
}
@@ -114,7 +119,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
}
if (!Strings.isNullOrEmpty(rsqlFilter)) {
- specList.add(RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class));
+ specList.add(RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer));
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
}
@@ -156,7 +161,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
@Override
public boolean verifyTargetFilterQuerySyntax(final String query) {
- RSQLUtility.parse(query, TargetFields.class);
+ RSQLUtility.parse(query, TargetFields.class, virtualPropertyReplacer);
return true;
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java
index c3cc2a36c..f2eac4051 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java
@@ -13,7 +13,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
@@ -29,6 +28,8 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.TargetFields;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
@@ -43,6 +44,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
+import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Target;
@@ -68,7 +70,6 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
-import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
@@ -104,6 +105,9 @@ public class JpaTargetManagement implements TargetManagement {
@Autowired
private AfterTransactionCommitExecutor afterCommit;
+ @Autowired
+ private VirtualPropertyReplacer virtualPropertyReplacer;
+
@Override
public Target findTargetByControllerID(final String controllerId) {
return targetRepository.findByControllerId(controllerId);
@@ -154,12 +158,15 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice findTargetsAll(final TargetFilterQuery targetFilterQuery, final Pageable pageable) {
- return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class), pageable);
+ return findTargetsBySpec(
+ RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer),
+ pageable);
}
@Override
public Page findTargetsAll(final String targetFilterQuery, final Pageable pageable) {
- return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class), pageable);
+ return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class, virtualPropertyReplacer),
+ pageable);
}
private Page findTargetsBySpec(final Specification spec, final Pageable pageable) {
@@ -223,7 +230,8 @@ public class JpaTargetManagement implements TargetManagement {
public Page findTargetByAssignedDistributionSet(final Long distributionSetID, final String rsqlParam,
final Pageable pageReq) {
- final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class,
+ virtualPropertyReplacer);
return convertPage(
targetRepository
@@ -251,7 +259,8 @@ public class JpaTargetManagement implements TargetManagement {
public Page findTargetByInstalledDistributionSet(final Long distributionSetId, final String rsqlParam,
final Pageable pageable) {
- final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class);
+ final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class,
+ virtualPropertyReplacer);
return convertPage(
targetRepository
@@ -269,42 +278,56 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice findTargetByFilters(final Pageable pageable, final Collection status,
- final String searchText, final Long installedOrAssignedDistributionSetId,
+ final Boolean overdueState, final String searchText, final Long installedOrAssignedDistributionSetId,
final Boolean selectTargetWithNoTag, final String... tagNames) {
- final List> specList = buildSpecificationList(status, searchText,
- installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames);
+ final List> specList = buildSpecificationList(
+ new FilterParams(installedOrAssignedDistributionSetId, status, overdueState, searchText,
+ selectTargetWithNoTag, tagNames),
+ true);
return findByCriteriaAPI(pageable, specList);
}
@Override
- public Long countTargetByFilters(final Collection status, final String searchText,
- final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag,
- final String... tagNames) {
- final List> specList = buildSpecificationList(status, searchText,
- installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames);
+ public Long countTargetByFilters(final Collection status, final Boolean overdueState,
+ final String searchText, final Long installedOrAssignedDistributionSetId,
+ final Boolean selectTargetWithNoTag, final String... tagNames) {
+ final List> specList = buildSpecificationList(
+ new FilterParams(installedOrAssignedDistributionSetId, status, overdueState, searchText,
+ selectTargetWithNoTag, tagNames),
+ true);
return countByCriteriaAPI(specList);
}
- private static List> buildSpecificationList(final Collection status,
- final String searchText, final Long installedOrAssignedDistributionSetId,
- final Boolean selectTargetWithNoTag, final boolean fetch, final String... tagNames) {
- final List> specList = new LinkedList<>();
- if (status != null && !status.isEmpty()) {
- specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch));
+ private static List> buildSpecificationList(final FilterParams filterParams,
+ final boolean fetch) {
+ final List> specList = new ArrayList<>();
+ if (filterParams.getFilterByStatus() != null && !filterParams.getFilterByStatus().isEmpty()) {
+ specList.add(TargetSpecifications.hasTargetUpdateStatus(filterParams.getFilterByStatus(), fetch));
}
- if (installedOrAssignedDistributionSetId != null) {
+ if (filterParams.getOverdueState() != null) {
specList.add(
- TargetSpecifications.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
+ TargetSpecifications.isOverdue(TimestampCalculator.calculateOverdueTimestamp()));
}
- if (!Strings.isNullOrEmpty(searchText)) {
- specList.add(TargetSpecifications.likeNameOrDescriptionOrIp(searchText));
+ if (filterParams.getFilterByDistributionId() != null) {
+ specList.add(
+ TargetSpecifications
+ .hasInstalledOrAssignedDistributionSet(filterParams.getFilterByDistributionId()));
}
- if (selectTargetWithNoTag != null && (selectTargetWithNoTag || (tagNames != null && tagNames.length > 0))) {
- specList.add(TargetSpecifications.hasTags(tagNames, selectTargetWithNoTag));
+ if (StringUtils.isNotEmpty(filterParams.getFilterBySearchText())) {
+ specList.add(TargetSpecifications.likeNameOrDescriptionOrIp(filterParams.getFilterBySearchText()));
+ }
+ if (isHasTagsFilterActive(filterParams)) {
+ specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(),
+ filterParams.getSelectTargetWithNoTag()));
}
return specList;
}
+ private static boolean isHasTagsFilterActive(final FilterParams filterParams) {
+ return filterParams.getSelectTargetWithNoTag() != null && (filterParams.getSelectTargetWithNoTag()
+ || (filterParams.getFilterByTagNames() != null && filterParams.getFilterByTagNames().length > 0));
+ }
+
private Slice findByCriteriaAPI(final Pageable pageable, final List> specList) {
if (specList == null || specList.isEmpty()) {
return convertPage(criteriaNoCountDao.findAll(pageable, JpaTarget.class), pageable);
@@ -418,9 +441,8 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice findTargetsAllOrderByLinkedDistributionSet(final Pageable pageable,
- final Long orderByDistributionId, final Long filterByDistributionId,
- final Collection filterByStatus, final String filterBySearchText,
- final Boolean selectTargetWithNoTag, final String... filterByTagNames) {
+ final Long orderByDistributionId, final FilterParams filterParams) {
+
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery query = cb.createQuery(JpaTarget.class);
final Root targetRoot = query.from(JpaTarget.class);
@@ -443,8 +465,7 @@ public class JpaTargetManagement implements TargetManagement {
// build the specifications and then to predicates necessary by the
// given filters
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
- buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
- selectTargetWithNoTag, true, filterByTagNames),
+ buildSpecificationList(filterParams, true),
targetRoot, query, cb);
// if we have some predicates then add it to the where clause of the
@@ -500,7 +521,8 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public List findAllTargetIdsByFilters(final Pageable pageRequest,
- final Collection filterByStatus, final String filterBySearchText,
+ final Collection filterByStatus, final Boolean overdueState,
+ final String filterBySearchText,
final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag,
final String... filterByTagNames) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
@@ -517,8 +539,9 @@ public class JpaTargetManagement implements TargetManagement {
targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name), targetRoot.get(sortProperty));
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
- buildSpecificationList(filterByStatus, filterBySearchText, installedOrAssignedDistributionSetId,
- selectTargetWithNoTag, false, filterByTagNames),
+ buildSpecificationList(new FilterParams(installedOrAssignedDistributionSetId, filterByStatus,
+ overdueState, filterBySearchText,
+ selectTargetWithNoTag, filterByTagNames), false),
targetRoot, multiselect, cb);
// if we have some predicates then add it to the where clause of the
@@ -547,7 +570,8 @@ public class JpaTargetManagement implements TargetManagement {
final CriteriaQuery