Optimized implementation of VirtualPropertyReplacer.

Added auto configuration for VirtualPropertyResolver.

Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com>
This commit is contained in:
Dominik Herbst
2016-09-28 13:54:54 +02:00
parent 9265f17e19
commit b1d9930d94
18 changed files with 106 additions and 76 deletions

View File

@@ -9,12 +9,16 @@
package org.eclipse.hawkbit.autoconfigure.repository; package org.eclipse.hawkbit.autoconfigure.repository;
import org.eclipse.hawkbit.EnableJpaRepository; 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.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.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
/** /**
* Auto-Configuration for enabling the REST-Resources. * Auto-Configuration for enabling JPA repository.
* *
*/ */
@Configuration @Configuration
@@ -22,4 +26,14 @@ import org.springframework.context.annotation.Import;
@Import({ EnableJpaRepository.class }) @Import({ EnableJpaRepository.class })
public class JpaRepositoryAutoConfiguration { public class JpaRepositoryAutoConfiguration {
/**
*
* @return returns a VirtualPropertyReplacer
*/
@Bean
@ConditionalOnMissingBean
public VirtualPropertyReplacer virtualPropertyReplacer() {
return new VirtualPropertyResolver();
}
} }

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.repository.rsql;
/** /**
* Implementations map a placeholder to the associated value. * Implementations map a placeholder to the associated value.
@@ -14,15 +14,15 @@ package org.eclipse.hawkbit.repository.jpa.rsql;
* This is used in context of string replacement. * This is used in context of string replacement.
*/ */
@FunctionalInterface @FunctionalInterface
public interface VirtualPropertyLookup { public interface VirtualPropertyReplacer {
/** /**
* Looks up a placeholder to the associated value. * Looks up a placeholders and replaces them
* *
* @param placeholder * @param input
* the virtual property that should be resolved by a value * the input string in which virtual properties should be
* @return the value for the placeholder; may be <code>null</code> if no * replaced
* value could be found for the given placeholder; * @return the result of the replacement
*/ */
String lookup(String placeholder); String replace(String input);
} }

View File

@@ -15,15 +15,13 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.springframework.stereotype.Service;
/** /**
* Service that calculates non-persistent timestamps , e.g. the point a time a * Calculates non-persistent timestamps , e.g. the point a time a
* target is declared as overdue.<br> * target is declared as overdue.<br>
* Therefore tenant specific configuration may be considered. * Therefore tenant specific configuration may be considered.
* *
*/ */
@Service
public class TimestampCalculator { public class TimestampCalculator {
/** /**

View File

@@ -11,9 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql;
import java.time.Instant; import java.time.Instant;
import org.apache.commons.lang3.text.StrLookup; import org.apache.commons.lang3.text.StrLookup;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.eclipse.hawkbit.repository.jpa.TimestampCalculator; import org.eclipse.hawkbit.repository.jpa.TimestampCalculator;
import org.springframework.beans.factory.annotation.Autowired; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.stereotype.Component;
/** /**
* Adds macro capabilities to RSQL expressions that are used to filter for * Adds macro capabilities to RSQL expressions that are used to filter for
@@ -24,8 +24,8 @@ import org.springframework.stereotype.Component;
* time intervals).<br> * time intervals).<br>
* Such a virtual property needs to be calculated on Java-side before it may be * 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 * used in a target filter query that is passed to the database. Therefore a
* placeholder is used in the RSQL expression that is expanded in the * placeholder is used in the RSQL expression that is expanded when the RSQL is
* {@link RSQLUtility}. * parsed
* <p> * <p>
* A virtual property may either be a system value like the current date (aka * A virtual property may either be a system value like the current date (aka
* <em>now_ts</em>) or a value derived from (tenant-specific) system * <em>now_ts</em>) or a value derived from (tenant-specific) system
@@ -41,11 +41,11 @@ import org.springframework.stereotype.Component;
* configuration.</li> * configuration.</li>
* </ul> * </ul>
*/ */
@Component public class VirtualPropertyResolver extends StrLookup<String> implements VirtualPropertyReplacer {
public class VirtualPropertyResolver extends StrLookup<String> implements VirtualPropertyLookup {
@Autowired private final TimestampCalculator timestampCalculator = new TimestampCalculator();
private TimestampCalculator timestampCalculator;
private StrSubstitutor substitutor;
@Override @Override
public String lookup(String rhs) { public String lookup(String rhs) {
@@ -59,6 +59,15 @@ public class VirtualPropertyResolver extends StrLookup<String> implements Virtua
return resolved; 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);
}
TimestampCalculator getTimestampCalculator() { TimestampCalculator getTimestampCalculator() {
return timestampCalculator; return timestampCalculator;
} }

View File

@@ -54,7 +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.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
@@ -136,7 +136,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
private SystemSecurityContext systemSecurityContext; private SystemSecurityContext systemSecurityContext;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
@@ -609,7 +609,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
} }
private Specification<JpaAction> createSpecificationFor(final Target target, final String rsqlParam) { private Specification<JpaAction> createSpecificationFor(final Target target, final String rsqlParam) {
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class, virtualPropertyLookup); final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class, virtualPropertyReplacer);
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb), return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
cb.equal(root.get(JpaAction_.target), target)); cb.equal(root.get(JpaAction_.target), target));
} }

View File

@@ -42,7 +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.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
@@ -109,7 +109,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
private TenantAware tenantAware; private TenantAware tenantAware;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) { public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
@@ -283,7 +283,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override @Override
public Page<DistributionSetType> findDistributionSetTypesAll(final String rsqlParam, final Pageable pageable) { public Page<DistributionSetType> findDistributionSetTypesAll(final String rsqlParam, final Pageable pageable) {
final Specification<JpaDistributionSetType> spec = RSQLUtility.parse(rsqlParam, final Specification<JpaDistributionSetType> spec = RSQLUtility.parse(rsqlParam,
DistributionSetTypeFields.class, virtualPropertyLookup); DistributionSetTypeFields.class, virtualPropertyReplacer);
return convertDsTPage(distributionSetTypeRepository.findAll(spec, pageable)); return convertDsTPage(distributionSetTypeRepository.findAll(spec, pageable));
} }
@@ -350,7 +350,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
final Boolean deleted) { final Boolean deleted) {
final Specification<JpaDistributionSet> spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class, final Specification<JpaDistributionSet> spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>(2); final List<Specification<JpaDistributionSet>> specList = new ArrayList<>(2);
if (deleted != null) { if (deleted != null) {
@@ -562,7 +562,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
final String rsqlParam, final Pageable pageable) { final String rsqlParam, final Pageable pageable) {
final Specification<JpaDistributionSetMetadata> spec = RSQLUtility.parse(rsqlParam, final Specification<JpaDistributionSetMetadata> spec = RSQLUtility.parse(rsqlParam,
DistributionSetMetadataFields.class, virtualPropertyLookup); DistributionSetMetadataFields.class, virtualPropertyReplacer);
return convertMdPage( return convertMdPage(
distributionSetMetadataRepository distributionSetMetadataRepository

View File

@@ -33,7 +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.model.RolloutTargetGroup_; import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup_;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
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;
@@ -72,7 +72,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
private EntityManager entityManager; private EntityManager entityManager;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
public RolloutGroup findRolloutGroupById(final Long rolloutGroupId) { public RolloutGroup findRolloutGroupById(final Long rolloutGroupId) {
@@ -97,7 +97,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
final Pageable pageable) { final Pageable pageable) {
final Specification<JpaRolloutGroup> specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class, final Specification<JpaRolloutGroup> specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertPage( return convertPage(
rolloutGroupRepository rolloutGroupRepository
@@ -151,7 +151,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
final Pageable pageable) { final Pageable pageable) {
final Specification<JpaTarget> rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class, final Specification<JpaTarget> rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> { return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> {
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup); final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup);

View File

@@ -32,7 +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.RolloutGroupActionEvaluator;
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.model.Action; 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.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -116,7 +116,7 @@ public class JpaRolloutManagement implements RolloutManagement {
private CacheWriteNotify cacheWriteNotify; private CacheWriteNotify cacheWriteNotify;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Autowired @Autowired
@Qualifier("asyncExecutor") @Qualifier("asyncExecutor")
@@ -155,7 +155,7 @@ public class JpaRolloutManagement implements RolloutManagement {
public Page<Rollout> findAllWithDetailedStatusByPredicate(final String rsqlParam, final Pageable pageable) { public Page<Rollout> findAllWithDetailedStatusByPredicate(final String rsqlParam, final Pageable pageable) {
final Specification<JpaRollout> specification = RSQLUtility.parse(rsqlParam, RolloutFields.class, final Specification<JpaRollout> specification = RSQLUtility.parse(rsqlParam, RolloutFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
final Page<JpaRollout> findAll = rolloutRepository.findAll(specification, pageable); final Page<JpaRollout> findAll = rolloutRepository.findAll(specification, pageable);
setRolloutStatusDetails(findAll); setRolloutStatusDetails(findAll);

View File

@@ -45,7 +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.JpaSoftwareModule_;
import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey; import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule;
@@ -108,7 +108,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
private ArtifactManagement artifactManagement; private ArtifactManagement artifactManagement;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
@Modifying @Modifying
@@ -317,7 +317,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override @Override
public Page<SoftwareModule> findSoftwareModulesByPredicate(final String rsqlParam, final Pageable pageable) { public Page<SoftwareModule> findSoftwareModulesByPredicate(final String rsqlParam, final Pageable pageable) {
final Specification<JpaSoftwareModule> spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class, final Specification<JpaSoftwareModule> spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable); return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable);
} }
@@ -326,7 +326,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
public Page<SoftwareModuleType> findSoftwareModuleTypesAll(final String rsqlParam, final Pageable pageable) { public Page<SoftwareModuleType> findSoftwareModuleTypesAll(final String rsqlParam, final Pageable pageable) {
final Specification<JpaSoftwareModuleType> spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class, final Specification<JpaSoftwareModuleType> spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable); return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable);
} }
@@ -612,7 +612,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
final String rsqlParam, final Pageable pageable) { final String rsqlParam, final Pageable pageable) {
final Specification<JpaSoftwareModuleMetadata> spec = RSQLUtility.parse(rsqlParam, final Specification<JpaSoftwareModuleMetadata> spec = RSQLUtility.parse(rsqlParam,
SoftwareModuleMetadataFields.class, virtualPropertyLookup); SoftwareModuleMetadataFields.class, virtualPropertyReplacer);
return convertSmMdPage( return convertSmMdPage(
softwareModuleMetadataRepository softwareModuleMetadataRepository
.findAll( .findAll(

View File

@@ -30,7 +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.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
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.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
@@ -76,7 +76,7 @@ public class JpaTagManagement implements TagManagement {
private AfterTransactionCommitExecutor afterCommit; private AfterTransactionCommitExecutor afterCommit;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
public TargetTag findTargetTag(final String name) { public TargetTag findTargetTag(final String name) {
@@ -151,7 +151,7 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
public Page<TargetTag> findAllTargetTags(final String rsqlParam, final Pageable pageable) { public Page<TargetTag> findAllTargetTags(final String rsqlParam, final Pageable pageable) {
final Specification<JpaTargetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class, virtualPropertyLookup); final Specification<JpaTargetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class, virtualPropertyReplacer);
return convertTPage(targetTagRepository.findAll(spec, pageable), pageable); return convertTPage(targetTagRepository.findAll(spec, pageable), pageable);
} }
@@ -285,7 +285,7 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
public Page<DistributionSetTag> findAllDistributionSetTags(final String rsqlParam, final Pageable pageable) { public Page<DistributionSetTag> findAllDistributionSetTags(final String rsqlParam, final Pageable pageable) {
final Specification<JpaDistributionSetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class, final Specification<JpaDistributionSetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable); return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable);
} }

View File

@@ -16,7 +16,7 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification; import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
@@ -46,7 +46,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
private TargetFilterQueryRepository targetFilterQueryRepository; private TargetFilterQueryRepository targetFilterQueryRepository;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
@Modifying @Modifying
@@ -115,7 +115,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
@Override @Override
public boolean verifyTargetFilterQuerySyntax(final String query) { public boolean verifyTargetFilterQuerySyntax(final String query) {
RSQLUtility.parse(query, TargetFields.class, virtualPropertyLookup); RSQLUtility.parse(query, TargetFields.class, virtualPropertyReplacer);
return true; return true;
} }

View File

@@ -42,7 +42,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
@@ -105,7 +105,7 @@ public class JpaTargetManagement implements TargetManagement {
private AfterTransactionCommitExecutor afterCommit; private AfterTransactionCommitExecutor afterCommit;
@Autowired @Autowired
private VirtualPropertyLookup virtualPropertyLookup; private VirtualPropertyReplacer virtualPropertyReplacer;
@Override @Override
public Target findTargetByControllerID(final String controllerId) { public Target findTargetByControllerID(final String controllerId) {
@@ -158,13 +158,13 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Slice<Target> findTargetsAll(final TargetFilterQuery targetFilterQuery, final Pageable pageable) { public Slice<Target> findTargetsAll(final TargetFilterQuery targetFilterQuery, final Pageable pageable) {
return findTargetsBySpec( return findTargetsBySpec(
RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyLookup), RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer),
pageable); pageable);
} }
@Override @Override
public Page<Target> findTargetsAll(final String targetFilterQuery, final Pageable pageable) { public Page<Target> findTargetsAll(final String targetFilterQuery, final Pageable pageable) {
return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class, virtualPropertyLookup), return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class, virtualPropertyReplacer),
pageable); pageable);
} }
@@ -233,7 +233,7 @@ public class JpaTargetManagement implements TargetManagement {
final Pageable pageReq) { final Pageable pageReq) {
final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class, final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertPage( return convertPage(
targetRepository targetRepository
@@ -262,7 +262,7 @@ public class JpaTargetManagement implements TargetManagement {
final Pageable pageable) { final Pageable pageable) {
final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class, final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return convertPage( return convertPage(
targetRepository targetRepository
@@ -566,7 +566,7 @@ public class JpaTargetManagement implements TargetManagement {
final CriteriaQuery<Object[]> multiselect = query.multiselect(targetRoot.get(JpaTarget_.id), final CriteriaQuery<Object[]> multiselect = query.multiselect(targetRoot.get(JpaTarget_.id),
targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name), targetRoot.get(sortProperty)); targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name), targetRoot.get(sortProperty));
final Specification<JpaTarget> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyLookup); final Specification<JpaTarget> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer);
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(Lists.newArrayList(spec), targetRoot, final Predicate[] specificationsForMultiSelect = specificationsToPredicate(Lists.newArrayList(spec), targetRoot,
multiselect, cb); multiselect, cb);
@@ -645,14 +645,14 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Long countTargetByTargetFilterQuery(final TargetFilterQuery targetFilterQuery) { public Long countTargetByTargetFilterQuery(final TargetFilterQuery targetFilterQuery) {
final Specification<JpaTarget> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, final Specification<JpaTarget> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return targetRepository.count(specs); return targetRepository.count(specs);
} }
@Override @Override
public Long countTargetByTargetFilterQuery(final String targetFilterQuery) { public Long countTargetByTargetFilterQuery(final String targetFilterQuery) {
final Specification<JpaTarget> specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class, final Specification<JpaTarget> specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class,
virtualPropertyLookup); virtualPropertyReplacer);
return targetRepository.count(specs); return targetRepository.count(specs);
} }

View File

@@ -26,11 +26,11 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.apache.commons.lang3.text.StrLookup; import org.apache.commons.lang3.text.StrLookup;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.eclipse.hawkbit.repository.FieldNameProvider; import org.eclipse.hawkbit.repository.FieldNameProvider;
import org.eclipse.hawkbit.repository.FieldValueConverter; import org.eclipse.hawkbit.repository.FieldValueConverter;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.SimpleTypeConverter; import org.springframework.beans.SimpleTypeConverter;
@@ -99,7 +99,7 @@ public final class RSQLUtility {
* @param fieldNameProvider * @param fieldNameProvider
* the enum class type which implements the * the enum class type which implements the
* {@link FieldNameProvider} * {@link FieldNameProvider}
* @param virtualPropertyLookup * @param virtualPropertyReplacer
* holds the logic how the known macros have to be resolved; may * holds the logic how the known macros have to be resolved; may
* be <code>null</code> * be <code>null</code>
* @return an specification which can be used with JPA * @return an specification which can be used with JPA
@@ -110,8 +110,8 @@ public final class RSQLUtility {
* if the RSQL syntax is wrong * if the RSQL syntax is wrong
*/ */
public static <A extends Enum<A> & FieldNameProvider, T> Specification<T> parse(final String rsql, public static <A extends Enum<A> & FieldNameProvider, T> Specification<T> parse(final String rsql,
final Class<A> fieldNameProvider, VirtualPropertyLookup virtualPropertyLookup) { final Class<A> fieldNameProvider, VirtualPropertyReplacer virtualPropertyReplacer) {
return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, virtualPropertyLookup); return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, virtualPropertyReplacer);
} }
/** /**
@@ -142,13 +142,13 @@ public final class RSQLUtility {
private final String rsql; private final String rsql;
private final Class<A> enumType; private final Class<A> enumType;
private final VirtualPropertyLookup virtualPropertyLookup; private final VirtualPropertyReplacer virtualPropertyReplacer;
private RSQLSpecification(final String rsql, final Class<A> enumType, private RSQLSpecification(final String rsql, final Class<A> enumType,
VirtualPropertyLookup virtualPropertyLookup) { VirtualPropertyReplacer virtualPropertyReplacer) {
this.rsql = rsql; this.rsql = rsql;
this.enumType = enumType; this.enumType = enumType;
this.virtualPropertyLookup = virtualPropertyLookup; this.virtualPropertyReplacer = virtualPropertyReplacer;
} }
@Override @Override
@@ -157,7 +157,7 @@ public final class RSQLUtility {
final Node rootNode = parseRsql(rsql); final Node rootNode = parseRsql(rsql);
final JpqQueryRSQLVisitor<A, T> jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType, final JpqQueryRSQLVisitor<A, T> jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType,
virtualPropertyLookup); virtualPropertyReplacer);
final List<Predicate> accept = rootNode.<List<Predicate>, String> accept(jpqQueryRSQLVisitor); final List<Predicate> accept = rootNode.<List<Predicate>, String> accept(jpqQueryRSQLVisitor);
if (accept != null && !accept.isEmpty()) { if (accept != null && !accept.isEmpty()) {
@@ -187,19 +187,16 @@ public final class RSQLUtility {
private final Root<T> root; private final Root<T> root;
private final CriteriaBuilder cb; private final CriteriaBuilder cb;
private final Class<A> enumType; private final Class<A> enumType;
private final StrSubstitutor substitutor; private final VirtualPropertyReplacer virtualPropertyReplacer;
private final SimpleTypeConverter simpleTypeConverter; private final SimpleTypeConverter simpleTypeConverter;
private JpqQueryRSQLVisitor(final Root<T> root, final CriteriaBuilder cb, final Class<A> enumType, private JpqQueryRSQLVisitor(final Root<T> root, final CriteriaBuilder cb, final Class<A> enumType,
VirtualPropertyLookup virtualPropertyLookup) { VirtualPropertyReplacer virtualPropertyReplacer) {
this.root = root; this.root = root;
this.cb = cb; this.cb = cb;
this.enumType = enumType; this.enumType = enumType;
this.substitutor = (virtualPropertyLookup != null && virtualPropertyLookup instanceof StrLookup) this.virtualPropertyReplacer = virtualPropertyReplacer;
? new StrSubstitutor((StrLookup)virtualPropertyLookup, StrSubstitutor.DEFAULT_PREFIX,
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE)
: null;
simpleTypeConverter = new SimpleTypeConverter(); simpleTypeConverter = new SimpleTypeConverter();
} }
@@ -446,8 +443,8 @@ public final class RSQLUtility {
final String value; final String value;
// if lookup is available, replace macros ... // if lookup is available, replace macros ...
if (substitutor != null) { if (virtualPropertyReplacer != null) {
value = substitutor.replace(values.get(0)); value = virtualPropertyReplacer.replace(values.get(0));
} else { } else {
value = values.get(0); value = values.get(0);
} }

View File

@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc
import org.eclipse.hawkbit.repository.jpa.TimestampCalculator; import org.eclipse.hawkbit.repository.jpa.TimestampCalculator;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -321,7 +322,7 @@ public class RSQLUtilityTest {
eq(overduePropPlaceholder)); eq(overduePropPlaceholder));
} }
public VirtualPropertyLookup setupMacroLookup() { public VirtualPropertyReplacer setupMacroLookup() {
when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class)) when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class))
.thenReturn(TEST_POLLING_TIME_INTERVAL); .thenReturn(TEST_POLLING_TIME_INTERVAL);
when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class)) when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class))

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.repository.jpa.rsql; package org.eclipse.hawkbit.repository.jpa.rsql;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.time.Instant; import java.time.Instant;

View File

@@ -15,6 +15,8 @@ import org.eclipse.hawkbit.cache.CacheConstants;
import org.eclipse.hawkbit.cache.TenancyCacheManager; import org.eclipse.hawkbit.cache.TenancyCacheManager;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.test.util.JpaTestRepositoryManagement; import org.eclipse.hawkbit.repository.test.util.JpaTestRepositoryManagement;
import org.eclipse.hawkbit.repository.test.util.TestRepositoryManagement; import org.eclipse.hawkbit.repository.test.util.TestRepositoryManagement;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
@@ -120,4 +122,13 @@ public class TestConfiguration implements AsyncConfigurer {
return new SimpleAsyncUncaughtExceptionHandler(); return new SimpleAsyncUncaughtExceptionHandler();
} }
/**
*
* @return returns a VirtualPropertyReplacer
*/
@Bean
public VirtualPropertyReplacer virtualPropertyReplacer() {
return new VirtualPropertyResolver();
}
} }

View File

@@ -43,9 +43,8 @@ public final class FilterQueryValidation {
/** /**
* method for get ExpectedTokens. * method for get ExpectedTokens.
* *
* @param input * @param input RSQL filter
* @param entityManager * @return Validation result
* @return
*/ */
public static ValidationResult getExpectedTokens(final String input) { public static ValidationResult getExpectedTokens(final String input) {