Fix findings from overdue review:
* Introduce VirtualPropertyLookup interface * Remove Apache StrLookup from signature and use VirtualPropertyLookup * Use (internal) adapter to adapt VirtualPropertyLookup to StrLookup * Use interface instead of implementation for auto-wiring * Extract calculation for overdue_ts to service TimestampCalculator Signed-off-by: Marcel Mager (INST-IOT/ESB) <Marcel.Mager@bosch-si.com>
This commit is contained in:
@@ -52,7 +52,6 @@ import org.eclipse.hawkbit.repository.jpa.model.helper.SystemManagementHolder;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyMakroResolver;
|
|
||||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
@@ -392,14 +391,4 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
return new JpaEntityFactory();
|
return new JpaEntityFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link VirtualPropertyMakroResolver} bean.
|
|
||||||
*
|
|
||||||
* @return a new {@link VirtualPropertyMakroResolver}
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public VirtualPropertyMakroResolver virtualPropertyMakroResolver() {
|
|
||||||
return new VirtualPropertyMakroResolver();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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.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;
|
||||||
@@ -134,6 +135,9 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SystemSecurityContext systemSecurityContext;
|
private SystemSecurityContext systemSecurityContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
@Modifying
|
@Modifying
|
||||||
@@ -605,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);
|
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class, virtualPropertyLookup);
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,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.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;
|
||||||
@@ -107,6 +108,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TenantAware tenantAware;
|
private TenantAware tenantAware;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
|
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
|
||||||
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
|
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
|
||||||
@@ -286,7 +290,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);
|
DistributionSetTypeFields.class, virtualPropertyLookup);
|
||||||
|
|
||||||
return convertDsTPage(distributionSetTypeRepository.findAll(spec, pageable));
|
return convertDsTPage(distributionSetTypeRepository.findAll(spec, pageable));
|
||||||
}
|
}
|
||||||
@@ -352,7 +356,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
public Page<DistributionSet> findDistributionSetsAll(final String rsqlParam, final Pageable pageReq,
|
public Page<DistributionSet> findDistributionSetsAll(final String rsqlParam, final Pageable pageReq,
|
||||||
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);
|
||||||
|
|
||||||
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>();
|
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>();
|
||||||
if (deleted != null) {
|
if (deleted != null) {
|
||||||
@@ -530,7 +535,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
/**
|
/**
|
||||||
* Method to get the latest distribution set based on ds ID after the
|
* Method to get the latest distribution set based on ds ID after the
|
||||||
* metadata changes for that distribution set.
|
* metadata changes for that distribution set.
|
||||||
*
|
*
|
||||||
* @param distributionSet
|
* @param distributionSet
|
||||||
* Distribution set
|
* Distribution set
|
||||||
*/
|
*/
|
||||||
@@ -566,7 +571,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);
|
DistributionSetMetadataFields.class, virtualPropertyLookup);
|
||||||
|
|
||||||
return convertMdPage(
|
return convertMdPage(
|
||||||
distributionSetMetadataRepository
|
distributionSetMetadataRepository
|
||||||
|
|||||||
@@ -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.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.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;
|
||||||
@@ -70,6 +71,9 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RolloutGroup findRolloutGroupById(final Long rolloutGroupId) {
|
public RolloutGroup findRolloutGroupById(final Long rolloutGroupId) {
|
||||||
return rolloutGroupRepository.findOne(rolloutGroupId);
|
return rolloutGroupRepository.findOne(rolloutGroupId);
|
||||||
@@ -92,7 +96,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
|||||||
public Page<RolloutGroup> findRolloutGroupsAll(final Rollout rollout, final String rsqlParam,
|
public Page<RolloutGroup> findRolloutGroupsAll(final Rollout rollout, final String rsqlParam,
|
||||||
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);
|
||||||
|
|
||||||
return convertPage(
|
return convertPage(
|
||||||
rolloutGroupRepository
|
rolloutGroupRepository
|
||||||
@@ -145,7 +150,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
|||||||
public Page<Target> findRolloutGroupTargets(final RolloutGroup rolloutGroup, final String rsqlParam,
|
public Page<Target> findRolloutGroupTargets(final RolloutGroup rolloutGroup, final String rsqlParam,
|
||||||
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);
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -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.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.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;
|
||||||
@@ -114,6 +115,9 @@ public class JpaRolloutManagement implements RolloutManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CacheWriteNotify cacheWriteNotify;
|
private CacheWriteNotify cacheWriteNotify;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("asyncExecutor")
|
@Qualifier("asyncExecutor")
|
||||||
private Executor executor;
|
private Executor executor;
|
||||||
@@ -150,7 +154,8 @@ public class JpaRolloutManagement implements RolloutManagement {
|
|||||||
@Override
|
@Override
|
||||||
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);
|
||||||
|
|
||||||
final Page<JpaRollout> findAll = rolloutRepository.findAll(specification, pageable);
|
final Page<JpaRollout> findAll = rolloutRepository.findAll(specification, pageable);
|
||||||
setRolloutStatusDetails(findAll);
|
setRolloutStatusDetails(findAll);
|
||||||
|
|||||||
@@ -42,6 +42,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.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;
|
||||||
@@ -102,6 +103,9 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ArtifactManagement artifactManagement;
|
private ArtifactManagement artifactManagement;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Modifying
|
@Modifying
|
||||||
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
||||||
@@ -312,7 +316,8 @@ 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);
|
||||||
|
|
||||||
return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable);
|
return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable);
|
||||||
}
|
}
|
||||||
@@ -320,7 +325,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
@Override
|
@Override
|
||||||
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);
|
||||||
|
|
||||||
return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable);
|
return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable);
|
||||||
}
|
}
|
||||||
@@ -609,7 +615,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);
|
SoftwareModuleMetadataFields.class, virtualPropertyLookup);
|
||||||
return convertSmMdPage(
|
return convertSmMdPage(
|
||||||
softwareModuleMetadataRepository
|
softwareModuleMetadataRepository
|
||||||
.findAll(
|
.findAll(
|
||||||
|
|||||||
@@ -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.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.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;
|
||||||
@@ -74,6 +75,9 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AfterTransactionCommitExecutor afterCommit;
|
private AfterTransactionCommitExecutor afterCommit;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TargetTag findTargetTag(final String name) {
|
public TargetTag findTargetTag(final String name) {
|
||||||
return targetTagRepository.findByNameEquals(name);
|
return targetTagRepository.findByNameEquals(name);
|
||||||
@@ -147,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);
|
final Specification<JpaTargetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class, virtualPropertyLookup);
|
||||||
return convertTPage(targetTagRepository.findAll(spec, pageable), pageable);
|
return convertTPage(targetTagRepository.findAll(spec, pageable), pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +283,8 @@ 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);
|
||||||
|
|
||||||
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable);
|
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.VirtualPropertyMakroResolver;
|
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup;
|
||||||
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 VirtualPropertyMakroResolver virtualPropMakroResolver;
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@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, virtualPropMakroResolver);
|
RSQLUtility.parse(query, TargetFields.class, virtualPropertyLookup);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,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.VirtualPropertyMakroResolver;
|
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyLookup;
|
||||||
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;
|
||||||
@@ -104,7 +104,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
private AfterTransactionCommitExecutor afterCommit;
|
private AfterTransactionCommitExecutor afterCommit;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private VirtualPropertyMakroResolver virtualPropMakroResolver;
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Target findTargetByControllerID(final String controllerId) {
|
public Target findTargetByControllerID(final String controllerId) {
|
||||||
@@ -157,13 +157,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, virtualPropMakroResolver),
|
RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyLookup),
|
||||||
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, virtualPropMakroResolver),
|
return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class, virtualPropertyLookup),
|
||||||
pageable);
|
pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +232,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,
|
||||||
virtualPropMakroResolver);
|
virtualPropertyLookup);
|
||||||
|
|
||||||
return convertPage(
|
return convertPage(
|
||||||
targetRepository
|
targetRepository
|
||||||
@@ -261,7 +261,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,
|
||||||
virtualPropMakroResolver);
|
virtualPropertyLookup);
|
||||||
|
|
||||||
return convertPage(
|
return convertPage(
|
||||||
targetRepository
|
targetRepository
|
||||||
@@ -304,7 +304,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
}
|
}
|
||||||
if (overdueState != null) {
|
if (overdueState != null) {
|
||||||
specList.add(
|
specList.add(
|
||||||
TargetSpecifications.isOverdue(new VirtualPropertyMakroResolver().calculateOverdueTimestamp()));
|
TargetSpecifications.isOverdue(new TimestampCalculator().calculateOverdueTimestamp()));
|
||||||
}
|
}
|
||||||
if (installedOrAssignedDistributionSetId != null) {
|
if (installedOrAssignedDistributionSetId != null) {
|
||||||
specList.add(
|
specList.add(
|
||||||
@@ -561,7 +561,7 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
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,
|
final Specification<JpaTarget> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class,
|
||||||
virtualPropMakroResolver);
|
virtualPropertyLookup);
|
||||||
final List<Specification<JpaTarget>> specList = new ArrayList<>();
|
final List<Specification<JpaTarget>> specList = new ArrayList<>();
|
||||||
specList.add(spec);
|
specList.add(spec);
|
||||||
|
|
||||||
@@ -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,
|
||||||
virtualPropMakroResolver);
|
virtualPropertyLookup);
|
||||||
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,
|
||||||
virtualPropMakroResolver);
|
virtualPropertyLookup);
|
||||||
return targetRepository.count(specs);
|
return targetRepository.count(specs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
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;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TimestampCalculator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the overdue timestamp (<em>overdue_ts</em>) based on the
|
||||||
|
* current timestamp and the intervals for polling and poll-overdue:
|
||||||
|
* <p>
|
||||||
|
* <em>overdue_ts = now_ts - pollingInterval -
|
||||||
|
* pollingOverdueInterval</em>;<br>
|
||||||
|
* <em>pollingInterval</em> and <em>pollingOverdueInterval</em> are
|
||||||
|
* retrieved from tenant-specific system configuration.
|
||||||
|
*
|
||||||
|
* @return <em>overdue_ts</em> in milliseconds since Unix epoch as long
|
||||||
|
* value
|
||||||
|
*/
|
||||||
|
public long calculateOverdueTimestamp() {
|
||||||
|
long overdueTs = Instant.now().toEpochMilli() //
|
||||||
|
- getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis() //
|
||||||
|
- getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis();
|
||||||
|
return overdueTs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Duration getDurationForKey(TenantConfigurationKey key) {
|
||||||
|
return DurationHelper.formattedStringToDuration(getRawStringForKey(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRawStringForKey(TenantConfigurationKey key) {
|
||||||
|
return getTenantConfigurationManagement().getConfigurationValue(key, String.class).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TenantConfigurationManagement getTenantConfigurationManagement() {
|
||||||
|
return TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,12 +70,12 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor;
|
|||||||
* <li>name==targetId1 or description==plugAndPlay or updateStatus==UNKNOWN</li>
|
* <li>name==targetId1 or description==plugAndPlay or updateStatus==UNKNOWN</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* There is also a mechanism that allows to refer to known makros that can resolved by an optional {@link StrLookup}
|
* There is also a mechanism that allows to refer to known macros that can resolved by an optional {@link StrLookup}
|
||||||
* (cp. {@link VirtualPropertyMakroResolver}).<br>
|
* (cp. {@link VirtualPropertyResolver}).<br>
|
||||||
* An example that queries for all overdue targets using the ${OVERDUE_TS} placeholder introduced by
|
* An example that queries for all overdue targets using the ${OVERDUE_TS} placeholder introduced by
|
||||||
* {@link VirtualPropertyMakroResolver} looks like this:<br>
|
* {@link VirtualPropertyResolver} looks like this:<br>
|
||||||
* <em>lastControllerRequestAt=le=${OVERDUE_TS}</em><br>
|
* <em>lastControllerRequestAt=le=${OVERDUE_TS}</em><br>
|
||||||
* It is possible to escape a makro expression by using a second '$': $${OVERDUE_TS} would prevent the ${OVERDUE_TS}
|
* It is possible to escape a macro expression by using a second '$': $${OVERDUE_TS} would prevent the ${OVERDUE_TS}
|
||||||
* token from being expanded.
|
* token from being expanded.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -99,6 +99,9 @@ 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
|
||||||
|
* holds the logic how the known macros have to be resolved; may
|
||||||
|
* be <code>null</code>
|
||||||
* @return an specification which can be used with JPA
|
* @return an specification which can be used with JPA
|
||||||
* @throws RSQLParameterUnsupportedFieldException
|
* @throws RSQLParameterUnsupportedFieldException
|
||||||
* if a field in the RSQL string is used but not provided by the
|
* if a field in the RSQL string is used but not provided by the
|
||||||
@@ -107,29 +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) {
|
final Class<A> fieldNameProvider, VirtualPropertyLookup virtualPropertyLookup) {
|
||||||
return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, new VirtualPropertyMakroResolver());
|
return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, virtualPropertyLookup);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parses an RSQL valid string into an JPA {@link Specification} which then can be used to filter for JPA entities
|
|
||||||
* with the given RSQL query.
|
|
||||||
*
|
|
||||||
* @param rsql
|
|
||||||
* the rsql query
|
|
||||||
* @param fieldNameProvider
|
|
||||||
* the enum class type which implements the {@link FieldNameProvider}
|
|
||||||
* @param makroLookup
|
|
||||||
* holds the logic how the known makros have to be resolved; may be <code>null</code>
|
|
||||||
* @return an specification which can be used with JPA
|
|
||||||
* @throws RSQLParameterUnsupportedFieldException
|
|
||||||
* if a field in the RSQL string is used but not provided by the given {@code fieldNameProvider}
|
|
||||||
* @throws RSQLParameterSyntaxException
|
|
||||||
* if the RSQL syntax is wrong
|
|
||||||
*/
|
|
||||||
public static <A extends Enum<A> & FieldNameProvider, T> Specification<T> parse(final String rsql,
|
|
||||||
final Class<A> fieldNameProvider, StrLookup<String> makroLookup) {
|
|
||||||
return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, makroLookup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,12 +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 StrLookup<String> makroLookup;
|
private final VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
private RSQLSpecification(final String rsql, final Class<A> enumType, StrLookup<String> makroLookup) {
|
private RSQLSpecification(final String rsql, final Class<A> enumType,
|
||||||
|
VirtualPropertyLookup virtualPropertyLookup) {
|
||||||
this.rsql = rsql;
|
this.rsql = rsql;
|
||||||
this.enumType = enumType;
|
this.enumType = enumType;
|
||||||
this.makroLookup = makroLookup;
|
this.virtualPropertyLookup = virtualPropertyLookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -174,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,
|
||||||
makroLookup);
|
virtualPropertyLookup);
|
||||||
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()) {
|
||||||
@@ -204,18 +187,19 @@ 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 StrLookup<String> makroLookup;
|
private final VirtualPropertyLookup virtualPropertyLookup;
|
||||||
private final StrSubstitutor substitutor;
|
private final StrSubstitutor substitutor;
|
||||||
|
|
||||||
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,
|
||||||
StrLookup<String> makroLookup) {
|
VirtualPropertyLookup virtualPropertyLookup) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.cb = cb;
|
this.cb = cb;
|
||||||
this.enumType = enumType;
|
this.enumType = enumType;
|
||||||
this.makroLookup = makroLookup;
|
this.virtualPropertyLookup = virtualPropertyLookup;
|
||||||
this.substitutor = new StrSubstitutor(makroLookup, StrSubstitutor.DEFAULT_PREFIX,
|
this.substitutor = new StrSubstitutor(new StrLookupAdapter(virtualPropertyLookup),
|
||||||
|
StrSubstitutor.DEFAULT_PREFIX,
|
||||||
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE);
|
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE);
|
||||||
simpleTypeConverter = new SimpleTypeConverter();
|
simpleTypeConverter = new SimpleTypeConverter();
|
||||||
}
|
}
|
||||||
@@ -387,13 +371,10 @@ public final class RSQLUtility {
|
|||||||
private Object convertValueIfNecessary(final ComparisonNode node, final A fieldName, final String value,
|
private Object convertValueIfNecessary(final ComparisonNode node, final A fieldName, final String value,
|
||||||
final Path<Object> fieldPath) {
|
final Path<Object> fieldPath) {
|
||||||
// in case the value of an rsql query e.g. type==application is an
|
// in case the value of an rsql query e.g. type==application is an
|
||||||
// enum we need to
|
// enum we need to handle it separately because JPA needs the
|
||||||
// handle it separately because JPA needs the correct java-type to
|
// correct java-type to build an expression. So String and numeric
|
||||||
// build an
|
// values JPA can do it by it's own but not for classes like enums.
|
||||||
// expression. So String and numeric values JPA can do it by it's
|
// So we need to transform the given value string into the enum
|
||||||
// own but not for
|
|
||||||
// classes like enums. So we need to transform the given value
|
|
||||||
// string into the enum
|
|
||||||
// class.
|
// class.
|
||||||
final Class<? extends Object> javaType = fieldPath.getJavaType();
|
final Class<? extends Object> javaType = fieldPath.getJavaType();
|
||||||
if (javaType != null && javaType.isEnum()) {
|
if (javaType != null && javaType.isEnum()) {
|
||||||
@@ -445,8 +426,7 @@ public final class RSQLUtility {
|
|||||||
return Enum.valueOf(tmpEnumType, value.toUpperCase());
|
return Enum.valueOf(tmpEnumType, value.toUpperCase());
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
// we could not transform the given string value into the enum
|
// we could not transform the given string value into the enum
|
||||||
// type, so ignore
|
// type, so ignore it and return null and do not filter
|
||||||
// it and return null and do not filter
|
|
||||||
LOGGER.info("given value {} cannot be transformed into the correct enum type {}", value.toUpperCase(),
|
LOGGER.info("given value {} cannot be transformed into the correct enum type {}", value.toUpperCase(),
|
||||||
javaType);
|
javaType);
|
||||||
LOGGER.debug("value cannot be transformed to an enum", e);
|
LOGGER.debug("value cannot be transformed to an enum", e);
|
||||||
@@ -461,12 +441,13 @@ public final class RSQLUtility {
|
|||||||
private List<Predicate> mapToPredicate(final ComparisonNode node, final Path<Object> fieldPath,
|
private List<Predicate> mapToPredicate(final ComparisonNode node, final Path<Object> fieldPath,
|
||||||
final List<String> values, final List<Object> transformedValues, final A enumField) {
|
final List<String> values, final List<Object> transformedValues, final A enumField) {
|
||||||
// only 'equal' and 'notEqual' can handle transformed value like
|
// only 'equal' and 'notEqual' can handle transformed value like
|
||||||
// enums. The JPA API
|
// enums. The JPA API cannot handle object types for greaterThan etc
|
||||||
// cannot handle object types for greaterThan etc methods.
|
// methods.
|
||||||
final Object transformedValue = transformedValues.get(0);
|
final Object transformedValue = transformedValues.get(0);
|
||||||
|
|
||||||
final String value;
|
final String value;
|
||||||
if (makroLookup != null) { // if substitutor is available, replace makros ...
|
if (virtualPropertyLookup != null) { // if lookup is available,
|
||||||
|
// replace macros ...
|
||||||
value = substitutor.replace(values.get(0));
|
value = substitutor.replace(values.get(0));
|
||||||
} else {
|
} else {
|
||||||
value = values.get(0);
|
value = values.get(0);
|
||||||
@@ -611,4 +592,28 @@ public final class RSQLUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts the <code>VirtualPropertyLookup</code> to <code>StrLookup</code>.
|
||||||
|
*/
|
||||||
|
final static class StrLookupAdapter extends StrLookup<String> {
|
||||||
|
|
||||||
|
private VirtualPropertyLookup virtualPropertyLookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param virtualPropertyLookup
|
||||||
|
* the lookup to adapt.
|
||||||
|
*/
|
||||||
|
StrLookupAdapter(VirtualPropertyLookup virtualPropertyLookup) {
|
||||||
|
this.virtualPropertyLookup = virtualPropertyLookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookup(String key) {
|
||||||
|
return virtualPropertyLookup.lookup(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementations map a placeholder to the associated value.
|
||||||
|
* <p>
|
||||||
|
* This is used in context of string replacement.
|
||||||
|
*/
|
||||||
|
public interface VirtualPropertyLookup {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up a placeholder to the associated value.
|
||||||
|
*
|
||||||
|
* @param placeholder
|
||||||
|
* the virtual property that should be resolved by a value
|
||||||
|
* @return the value for the placeholder; may be <code>null</code> if no
|
||||||
|
* value could be found for the given placeholder;
|
||||||
|
*/
|
||||||
|
public String lookup(String placeholder);
|
||||||
|
}
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2016 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.model.helper.TenantConfigurationManagementHolder;
|
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds makro capabilities to RSQL expressions that are used to filter for targets.
|
|
||||||
* <p>
|
|
||||||
* 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).<br>
|
|
||||||
* 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 in the
|
|
||||||
* {@link RSQLUtility} by a {@link StrSubstitutor}. This {@link StrSubstitutor} is configured with an instance of
|
|
||||||
* {@link VirtualPropertyMakroResolver} to resolve the known makros.
|
|
||||||
* <p>
|
|
||||||
* 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 configuration (e.g. <em>overdue_ts</em>).
|
|
||||||
* <p>
|
|
||||||
* Known values are:<br>
|
|
||||||
* <ul>
|
|
||||||
* <li><em>now_ts</em>: maps to system UTC time in milliseconds since Unix epoch as long value</li>
|
|
||||||
* <li><em>overdue_ts</em>: is a calculated value: <em>overdue_ts = now_ts - pollingInterval - pollingOverdueInterval
|
|
||||||
* </em>; pollingInterval and pollingOverdueInterval are retrieved from tenant-specific system configuration.</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class VirtualPropertyMakroResolver extends StrLookup<String> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String lookup(String rhs) {
|
|
||||||
String resolved = null;
|
|
||||||
|
|
||||||
if ("now_ts".equals(rhs.toLowerCase())) {
|
|
||||||
resolved = String.valueOf(Instant.now().toEpochMilli());
|
|
||||||
} else if ("overdue_ts".equals(rhs.toLowerCase())) {
|
|
||||||
resolved = String.valueOf(calculateOverdueTimestamp());
|
|
||||||
}
|
|
||||||
return resolved;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long calculateOverdueTimestamp() {
|
|
||||||
long overdueTs = Instant.now().toEpochMilli() //
|
|
||||||
- getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis() //
|
|
||||||
- getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis();
|
|
||||||
return overdueTs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Duration getDurationForKey(TenantConfigurationKey key) {
|
|
||||||
return DurationHelper.formattedStringToDuration(getRawStringForKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getRawStringForKey(TenantConfigurationKey key) {
|
|
||||||
return getTenantConfigurationManagement().getConfigurationValue(key, String.class).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
TenantConfigurationManagement getTenantConfigurationManagement() {
|
|
||||||
return TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2016 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.Instant;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.TimestampCalculator;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds macro capabilities to RSQL expressions that are used to filter for
|
||||||
|
* targets.
|
||||||
|
* <p>
|
||||||
|
* 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).<br>
|
||||||
|
* 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 in the
|
||||||
|
* {@link RSQLUtility}.
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* configuration (e.g. <em>overdue_ts</em>).
|
||||||
|
* <p>
|
||||||
|
* Known values are:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li><em>now_ts</em>: maps to system UTC time in milliseconds since Unix epoch
|
||||||
|
* as long value</li>
|
||||||
|
* <li><em>overdue_ts</em>: is a calculated value: <em>overdue_ts = now_ts -
|
||||||
|
* pollingInterval - pollingOverdueInterval</em>; pollingInterval and
|
||||||
|
* pollingOverdueInterval are retrieved from tenant-specific system
|
||||||
|
* configuration.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class VirtualPropertyResolver implements VirtualPropertyLookup {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TimestampCalculator timestampCalculator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookup(String rhs) {
|
||||||
|
String resolved = null;
|
||||||
|
|
||||||
|
if ("now_ts".equals(rhs.toLowerCase())) {
|
||||||
|
resolved = String.valueOf(Instant.now().toEpochMilli());
|
||||||
|
} else if ("overdue_ts".equals(rhs.toLowerCase())) {
|
||||||
|
resolved = String.valueOf(getTimestampCalculator().calculateOverdueTimestamp());
|
||||||
|
}
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimestampCalculator getTimestampCalculator() {
|
||||||
|
return timestampCalculator;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,6 @@ import javax.persistence.criteria.Predicate;
|
|||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import javax.persistence.metamodel.Attribute;
|
import javax.persistence.metamodel.Attribute;
|
||||||
|
|
||||||
import org.apache.commons.lang3.text.StrLookup;
|
|
||||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||||
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
||||||
@@ -28,6 +27,7 @@ import org.eclipse.hawkbit.repository.TargetFields;
|
|||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
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.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.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
@@ -49,11 +49,14 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
public class RSQLUtilityTest {
|
public class RSQLUtilityTest {
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
VirtualPropertyMakroResolver makroResolver = new VirtualPropertyMakroResolver();
|
VirtualPropertyResolver macroResolver = new VirtualPropertyResolver();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
TenantConfigurationManagement confMgmt;
|
TenantConfigurationManagement confMgmt;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
TimestampCalculator timestampCalculator;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Root<Object> baseSoftwareModuleRootMock;
|
private Root<Object> baseSoftwareModuleRootMock;
|
||||||
|
|
||||||
@@ -271,7 +274,7 @@ public class RSQLUtilityTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the resolution of overdue_ts placeholder in context of a RSQL expression.")
|
@Description("Tests the resolution of overdue_ts placeholder in context of a RSQL expression.")
|
||||||
public void correctRsqlWithOverdueMakro() {
|
public void correctRsqlWithOverdueMacro() {
|
||||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||||
final String overdueProp = "overdue_ts";
|
final String overdueProp = "overdue_ts";
|
||||||
final String overduePropPlaceholder = "${" + overdueProp + "}";
|
final String overduePropPlaceholder = "${" + overdueProp + "}";
|
||||||
@@ -283,12 +286,12 @@ public class RSQLUtilityTest {
|
|||||||
.thenReturn(mock(Predicate.class));
|
.thenReturn(mock(Predicate.class));
|
||||||
|
|
||||||
// test
|
// test
|
||||||
Predicate result = RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMakroLookup())
|
Predicate result = RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup())
|
||||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(makroResolver, times(1)).lookup(overdueProp);
|
verify(macroResolver, times(1)).lookup(overdueProp);
|
||||||
// the makro is already replaced when passed to #lessThanOrEqualTo -> the method is never invoked with the
|
// the macro is already replaced when passed to #lessThanOrEqualTo -> the method is never invoked with the
|
||||||
// placeholder:
|
// placeholder:
|
||||||
verify(criteriaBuilderMock, never()).lessThanOrEqualTo(eq(pathOfString(baseSoftwareModuleRootMock)),
|
verify(criteriaBuilderMock, never()).lessThanOrEqualTo(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||||
eq(overduePropPlaceholder));
|
eq(overduePropPlaceholder));
|
||||||
@@ -296,7 +299,7 @@ public class RSQLUtilityTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests RSQL expression with an unknown placeholder.")
|
@Description("Tests RSQL expression with an unknown placeholder.")
|
||||||
public void correctRsqlWithUnknownMakro() {
|
public void correctRsqlWithUnknownMacro() {
|
||||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||||
final String overdueProp = "unknown";
|
final String overdueProp = "unknown";
|
||||||
final String overduePropPlaceholder = "${" + overdueProp + "}";
|
final String overduePropPlaceholder = "${" + overdueProp + "}";
|
||||||
@@ -308,24 +311,30 @@ public class RSQLUtilityTest {
|
|||||||
.thenReturn(mock(Predicate.class));
|
.thenReturn(mock(Predicate.class));
|
||||||
|
|
||||||
// test
|
// test
|
||||||
Predicate result = RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMakroLookup())
|
Predicate result = RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup())
|
||||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(makroResolver, times(1)).lookup(overdueProp);
|
verify(macroResolver, times(1)).lookup(overdueProp);
|
||||||
// the makro is unknown and hence never replaced -> #lessThanOrEqualTo is invoked with the placeholder:
|
// the macro is unknown and hence never replaced -> #lessThanOrEqualTo is invoked with the placeholder:
|
||||||
verify(criteriaBuilderMock, times(1)).lessThanOrEqualTo(eq(pathOfString(baseSoftwareModuleRootMock)),
|
verify(criteriaBuilderMock, times(1)).lessThanOrEqualTo(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||||
eq(overduePropPlaceholder));
|
eq(overduePropPlaceholder));
|
||||||
}
|
}
|
||||||
|
|
||||||
public StrLookup<String> setupMakroLookup() {
|
public VirtualPropertyLookup 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))
|
||||||
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
|
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
|
||||||
when(makroResolver.getTenantConfigurationManagement()).thenReturn(confMgmt);
|
|
||||||
|
|
||||||
return makroResolver;
|
when(macroResolver.getTimestampCalculator()).thenReturn(new TimestampCalculator() {
|
||||||
|
@Override
|
||||||
|
protected TenantConfigurationManagement getTenantConfigurationManagement() {
|
||||||
|
return confMgmt;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return macroResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.time.Instant;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.text.StrSubstitutor;
|
import org.apache.commons.lang3.text.StrSubstitutor;
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.TimestampCalculator;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -31,10 +32,10 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
@Features("Unit Tests - Repository")
|
@Features("Unit Tests - Repository")
|
||||||
@Stories("Placeholder resolution for virtual properties")
|
@Stories("Placeholder resolution for virtual properties")
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class VirtualPropertyMakroResolverTest {
|
public class VirtualPropertyResolverTest {
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
VirtualPropertyMakroResolver resolverUnderTest = new VirtualPropertyMakroResolver();
|
VirtualPropertyResolver resolverUnderTest = new VirtualPropertyResolver();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
TenantConfigurationManagement confMgmt;
|
TenantConfigurationManagement confMgmt;
|
||||||
@@ -55,14 +56,21 @@ public class VirtualPropertyMakroResolverTest {
|
|||||||
.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))
|
||||||
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
|
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
|
||||||
when(resolverUnderTest.getTenantConfigurationManagement()).thenReturn(confMgmt);
|
|
||||||
|
|
||||||
this.substitutor = new StrSubstitutor(resolverUnderTest, StrSubstitutor.DEFAULT_PREFIX,
|
when(resolverUnderTest.getTimestampCalculator()).thenReturn(new TimestampCalculator() {
|
||||||
|
@Override
|
||||||
|
protected TenantConfigurationManagement getTenantConfigurationManagement() {
|
||||||
|
return confMgmt;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.substitutor = new StrSubstitutor(new RSQLUtility.StrLookupAdapter(resolverUnderTest),
|
||||||
|
StrSubstitutor.DEFAULT_PREFIX,
|
||||||
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE);
|
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyMakroResolver.")
|
@Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.")
|
||||||
public void resolveNowTimestampPlaceholder() {
|
public void resolveNowTimestampPlaceholder() {
|
||||||
String placeholder = "${NOW_TS}";
|
String placeholder = "${NOW_TS}";
|
||||||
String testString = "lhs=lt=" + placeholder;
|
String testString = "lhs=lt=" + placeholder;
|
||||||
@@ -72,7 +80,7 @@ public class VirtualPropertyMakroResolverTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests resolution of OVERDUE_TS by using a StrSubstitutor configured with the VirtualPropertyMakroResolver.")
|
@Description("Tests resolution of OVERDUE_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.")
|
||||||
public void resolveOverdueTimestampPlaceholder() {
|
public void resolveOverdueTimestampPlaceholder() {
|
||||||
String placeholder = "${OVERDUE_TS}";
|
String placeholder = "${OVERDUE_TS}";
|
||||||
String testString = "lhs=lt=" + placeholder;
|
String testString = "lhs=lt=" + placeholder;
|
||||||
@@ -82,7 +90,7 @@ public class VirtualPropertyMakroResolverTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests case insensititity of VirtualPropertyMakroResolver.")
|
@Description("Tests case insensititity of VirtualPropertyResolver.")
|
||||||
public void resolveOverdueTimestampPlaceholderLowerCase() {
|
public void resolveOverdueTimestampPlaceholderLowerCase() {
|
||||||
String placeholder = "${overdue_ts}";
|
String placeholder = "${overdue_ts}";
|
||||||
String testString = "lhs=lt=" + placeholder;
|
String testString = "lhs=lt=" + placeholder;
|
||||||
@@ -92,7 +100,7 @@ public class VirtualPropertyMakroResolverTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests VirtualPropertyMakroResolver with a placeholder unknown to VirtualPropertyMakroResolver.")
|
@Description("Tests VirtualPropertyResolver with a placeholder unknown to VirtualPropertyResolver.")
|
||||||
public void handleUnknownPlaceholder() {
|
public void handleUnknownPlaceholder() {
|
||||||
String placeholder = "${unknown}";
|
String placeholder = "${unknown}";
|
||||||
String testString = "lhs=lt=" + placeholder;
|
String testString = "lhs=lt=" + placeholder;
|
||||||
Reference in New Issue
Block a user