Merge pull request #9 from bsinno/MECS-1438_CREATE_FILTER_OPTIONS_FOR_MAP
ok
This commit is contained in:
@@ -36,16 +36,50 @@ public enum DistributionSetFields implements FieldNameProvider {
|
|||||||
/**
|
/**
|
||||||
* The id field.
|
* The id field.
|
||||||
*/
|
*/
|
||||||
ID("id");
|
ID("id"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tags field.
|
||||||
|
*/
|
||||||
|
TAG("tags.name"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sw type key field.
|
||||||
|
*/
|
||||||
|
TYPE("type.key"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The metadata.
|
||||||
|
*/
|
||||||
|
METADATA("metadata", "key", "value");
|
||||||
|
|
||||||
private final String fieldName;
|
private final String fieldName;
|
||||||
|
private String keyFieldName;
|
||||||
|
private String valueFieldName;
|
||||||
|
|
||||||
private DistributionSetFields(final String fieldName) {
|
private DistributionSetFields(final String fieldName) {
|
||||||
|
this(fieldName, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DistributionSetFields(final String fieldName, final String keyFieldName, final String valueFieldName) {
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
|
this.keyFieldName = keyFieldName;
|
||||||
|
this.valueFieldName = valueFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValueFieldName() {
|
||||||
|
return valueFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKeyFieldName() {
|
||||||
|
return keyFieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFieldName() {
|
public String getFieldName() {
|
||||||
return fieldName;
|
return fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,87 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository;
|
package org.eclipse.hawkbit.repository;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for declaring the name of the field described in the database
|
* An interface for declaring the name of the field described in the database
|
||||||
* which is used as string representation of the field, e.g. for sorting the
|
* which is used as string representation of the field, e.g. for sorting the
|
||||||
* fields over REST.
|
* fields over REST.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
|
||||||
public interface FieldNameProvider {
|
public interface FieldNameProvider {
|
||||||
|
/**
|
||||||
|
* Seperator for the sub attributes
|
||||||
|
*/
|
||||||
|
public static final String SUB_ATTRIBUTE_SEPERATOR = ".";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the string representation of the underlying persistence field
|
* @return the string representation of the underlying persistence field
|
||||||
* name e.g. in case of sorting. Never {@code null}.
|
* name e.g. in case of sorting. Never {@code null}.
|
||||||
*/
|
*/
|
||||||
String getFieldName();
|
String getFieldName();
|
||||||
|
|
||||||
|
default boolean containsSubEntityAttribute(final String propertyField) {
|
||||||
|
return FieldNameProvider.containsSubEntityAttribute(propertyField, getSubEntityAttributes());
|
||||||
|
};
|
||||||
|
|
||||||
|
default List<String> getSubEntityAttributes() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the database column for the key
|
||||||
|
*
|
||||||
|
* @return key fieldname
|
||||||
|
*/
|
||||||
|
default String getKeyFieldName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the database column for the value
|
||||||
|
*
|
||||||
|
* @return key fieldname
|
||||||
|
*/
|
||||||
|
default String getValueFieldName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the entity field a {@link Map}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
default boolean isMap() {
|
||||||
|
return getKeyFieldName() != null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a sub attribute exists.
|
||||||
|
*
|
||||||
|
* @param propertyField
|
||||||
|
* the sub property field.
|
||||||
|
* @param subEntityAttribues
|
||||||
|
* the list of available properties
|
||||||
|
* @return <true> property exists <false> not exists
|
||||||
|
*/
|
||||||
|
static boolean containsSubEntityAttribute(final String propertyField, final List<String> subEntityAttribues) {
|
||||||
|
if (subEntityAttribues.contains(propertyField)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (final String attribute : subEntityAttribues) {
|
||||||
|
final String[] graph = attribute.split("\\" + SUB_ATTRIBUTE_SEPERATOR);
|
||||||
|
|
||||||
|
for (final String subAttribute : graph) {
|
||||||
|
if (subAttribute.equalsIgnoreCase(propertyField)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,16 +36,38 @@ public enum SoftwareModuleFields implements FieldNameProvider {
|
|||||||
/**
|
/**
|
||||||
* The id field.
|
* The id field.
|
||||||
*/
|
*/
|
||||||
ID("id");
|
ID("id"),
|
||||||
|
/**
|
||||||
|
* The metadata.
|
||||||
|
*/
|
||||||
|
METADATA("metadata", "key", "value");
|
||||||
|
|
||||||
private final String fieldName;
|
private final String fieldName;
|
||||||
|
private String keyFieldName;
|
||||||
|
private String valueFieldName;
|
||||||
|
|
||||||
private SoftwareModuleFields(final String fieldName) {
|
private SoftwareModuleFields(final String fieldName) {
|
||||||
|
this(fieldName, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SoftwareModuleFields(final String fieldName, final String keyFieldName, final String valueFieldName) {
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
|
this.keyFieldName = keyFieldName;
|
||||||
|
this.valueFieldName = valueFieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFieldName() {
|
public String getFieldName() {
|
||||||
return fieldName;
|
return fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKeyFieldName() {
|
||||||
|
return keyFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValueFieldName() {
|
||||||
|
return valueFieldName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository;
|
package org.eclipse.hawkbit.repository;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describing the fields of the Target model which can be used in the REST API
|
* Describing the fields of the Target model which can be used in the REST API
|
||||||
* e.g. for sorting etc.
|
* e.g. for sorting etc.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public enum TargetFields implements FieldNameProvider {
|
public enum TargetFields implements FieldNameProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The controllerId field.
|
||||||
|
*/
|
||||||
|
ID("controllerId"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name field.
|
* The name field.
|
||||||
*/
|
*/
|
||||||
@@ -37,12 +44,49 @@ public enum TargetFields implements FieldNameProvider {
|
|||||||
/**
|
/**
|
||||||
* The ip-address field.
|
* The ip-address field.
|
||||||
*/
|
*/
|
||||||
IPADDRESS("targetInfo.ipAddress");
|
IPADDRESS("targetInfo.address"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attribute map of target info.
|
||||||
|
*/
|
||||||
|
ATTRIBUTE("targetInfo.controllerAttributes", true),
|
||||||
|
|
||||||
|
ASSIGNEDDS("assignedDistributionSet", "name", "version"),
|
||||||
|
/**
|
||||||
|
* The tags field.
|
||||||
|
*/
|
||||||
|
TAG("tags.name");
|
||||||
|
|
||||||
private final String fieldName;
|
private final String fieldName;
|
||||||
|
private List<String> subEntityAttribues;
|
||||||
|
private boolean mapField;
|
||||||
|
|
||||||
private TargetFields(final String fieldName) {
|
private TargetFields(final String fieldName) {
|
||||||
|
this(fieldName, false, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TargetFields(final String fieldName, final boolean isMapField) {
|
||||||
|
this(fieldName, isMapField, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TargetFields(final String fieldName, final String... subEntityAttribues) {
|
||||||
|
this(fieldName, false, Arrays.asList(subEntityAttribues));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TargetFields(final String fieldName, final boolean mapField, final List<String> subEntityAttribues) {
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
|
this.mapField = mapField;
|
||||||
|
this.subEntityAttribues = subEntityAttribues;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSubEntityAttributes() {
|
||||||
|
return subEntityAttribues;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMap() {
|
||||||
|
return mapField;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -205,8 +205,7 @@ public class TargetManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
public Slice<Target> findTargetsAll(@NotNull final TargetFilterQuery targetFilterQuery,
|
public Slice<Target> findTargetsAll(@NotNull final TargetFilterQuery targetFilterQuery,
|
||||||
@NotNull final Pageable pageable) {
|
@NotNull final Pageable pageable) {
|
||||||
return findTargetsAll(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, entityManager),
|
return findTargetsAll(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class), pageable);
|
||||||
pageable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -220,7 +219,7 @@ public class TargetManagement {
|
|||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
public Slice<Target> findTargetsAll(@NotNull final String targetFilterQuery, @NotNull final Pageable pageable) {
|
public Slice<Target> findTargetsAll(@NotNull final String targetFilterQuery, @NotNull final Pageable pageable) {
|
||||||
return findTargetsAll(RSQLUtility.parse(targetFilterQuery, TargetFields.class, entityManager), pageable);
|
return findTargetsAll(RSQLUtility.parse(targetFilterQuery, TargetFields.class), pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -351,9 +350,9 @@ public class TargetManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
|
||||||
public Page<Target> findTargetByAssignedDistributionSet(@NotNull final Long distributionSetID,
|
public Page<Target> findTargetByAssignedDistributionSet(@NotNull final Long distributionSetID,
|
||||||
final Specification<Target> spec, @NotNull final Pageable pageReq) {
|
final Specification<Target> spec, @NotNull final Pageable pageReq) {
|
||||||
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(
|
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(TargetSpecifications
|
||||||
TargetSpecifications.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb),
|
.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb), spec.toPredicate(root,
|
||||||
spec.toPredicate(root, query, cb)), pageReq);
|
query, cb)), pageReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,9 +389,9 @@ public class TargetManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
|
||||||
public Page<Target> findTargetByInstalledDistributionSet(final Long distributionSetId,
|
public Page<Target> findTargetByInstalledDistributionSet(final Long distributionSetId,
|
||||||
final Specification<Target> spec, final Pageable pageable) {
|
final Specification<Target> spec, final Pageable pageable) {
|
||||||
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(
|
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(TargetSpecifications
|
||||||
TargetSpecifications.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb),
|
.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb), spec.toPredicate(root,
|
||||||
spec.toPredicate(root, query, cb)), pageable);
|
query, cb)), pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -487,8 +486,8 @@ public class TargetManagement {
|
|||||||
specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch));
|
specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch));
|
||||||
}
|
}
|
||||||
if (installedOrAssignedDistributionSetId != null) {
|
if (installedOrAssignedDistributionSetId != null) {
|
||||||
specList.add(
|
specList.add(TargetSpecifications
|
||||||
TargetSpecifications.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
|
.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
|
||||||
}
|
}
|
||||||
if (!Strings.isNullOrEmpty(searchText)) {
|
if (!Strings.isNullOrEmpty(searchText)) {
|
||||||
specList.add(TargetSpecifications.likeNameOrDescriptionOrIp(searchText));
|
specList.add(TargetSpecifications.likeNameOrDescriptionOrIp(searchText));
|
||||||
@@ -560,8 +559,8 @@ public class TargetManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
||||||
public TargetTagAssigmentResult toggleTagAssignment(@NotEmpty final List<Target> targets,
|
public TargetTagAssigmentResult toggleTagAssignment(@NotEmpty final List<Target> targets,
|
||||||
@NotNull final TargetTag tag) {
|
@NotNull final TargetTag tag) {
|
||||||
return toggleTagAssignment(
|
return toggleTagAssignment(targets.stream().map(target -> target.getControllerId())
|
||||||
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList()), tag.getName());
|
.collect(Collectors.toList()), tag.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -584,8 +583,8 @@ public class TargetManagement {
|
|||||||
@NotNull final String tagName) {
|
@NotNull final String tagName) {
|
||||||
final TargetTag tag = targetTagRepository.findByNameEquals(tagName);
|
final TargetTag tag = targetTagRepository.findByNameEquals(tagName);
|
||||||
final List<Target> alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, targetIds);
|
final List<Target> alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, targetIds);
|
||||||
final List<Target> allTargets = targetRepository
|
final List<Target> allTargets = targetRepository.findAll(TargetSpecifications
|
||||||
.findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds));
|
.byControllerIdWithStatusAndTagsInJoin(targetIds));
|
||||||
|
|
||||||
// all are already assigned -> unassign
|
// all are already assigned -> unassign
|
||||||
if (alreadyAssignedTargets.size() == allTargets.size()) {
|
if (alreadyAssignedTargets.size() == allTargets.size()) {
|
||||||
@@ -741,20 +740,19 @@ public class TargetManagement {
|
|||||||
// select case expression to retrieve the case value as a column to be
|
// select case expression to retrieve the case value as a column to be
|
||||||
// able to order based on
|
// able to order based on
|
||||||
// this column, installed first,...
|
// this column, installed first,...
|
||||||
final Expression<Object> selectCase = cb.selectCase()
|
final Expression<Object> selectCase = cb
|
||||||
|
.selectCase()
|
||||||
.when(cb.equal(targetInfo.get(TargetInfo_.installedDistributionSet).get(DistributionSet_.id),
|
.when(cb.equal(targetInfo.get(TargetInfo_.installedDistributionSet).get(DistributionSet_.id),
|
||||||
orderByDistributionId), 1)
|
orderByDistributionId), 1)
|
||||||
.when(cb.equal(targetRoot.get(Target_.assignedDistributionSet).get(DistributionSet_.id),
|
.when(cb.equal(targetRoot.get(Target_.assignedDistributionSet).get(DistributionSet_.id),
|
||||||
orderByDistributionId), 2)
|
orderByDistributionId), 2).otherwise(100);
|
||||||
.otherwise(100);
|
|
||||||
// multiselect statement order by the select case and controllerId
|
// multiselect statement order by the select case and controllerId
|
||||||
query.distinct(true);
|
query.distinct(true);
|
||||||
// build the specifications and then to predicates necessary by the
|
// build the specifications and then to predicates necessary by the
|
||||||
// given filters
|
// given filters
|
||||||
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
|
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
|
||||||
buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
|
buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
|
||||||
selectTargetWithNoTag, true, filterByTagNames),
|
selectTargetWithNoTag, true, filterByTagNames), targetRoot, query, cb);
|
||||||
targetRoot, query, cb);
|
|
||||||
|
|
||||||
// if we have some predicates then add it to the where clause of the
|
// if we have some predicates then add it to the where clause of the
|
||||||
// multiselect
|
// multiselect
|
||||||
@@ -828,8 +826,9 @@ public class TargetManagement {
|
|||||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||||
final CriteriaQuery<TargetIdName> query = cb.createQuery(TargetIdName.class);
|
final CriteriaQuery<TargetIdName> query = cb.createQuery(TargetIdName.class);
|
||||||
final Root<Target> targetRoot = query.from(Target.class);
|
final Root<Target> targetRoot = query.from(Target.class);
|
||||||
return entityManager.createQuery(query.multiselect(targetRoot.get(Target_.id),
|
return entityManager.createQuery(
|
||||||
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name))).getResultList();
|
query.multiselect(targetRoot.get(Target_.id), targetRoot.get(Target_.controllerId),
|
||||||
|
targetRoot.get(Target_.name))).getResultList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,8 +870,7 @@ public class TargetManagement {
|
|||||||
|
|
||||||
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
|
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
|
||||||
buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
|
buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
|
||||||
selectTargetWithNoTag, false, filterByTagNames),
|
selectTargetWithNoTag, false, filterByTagNames), targetRoot, multiselect, cb);
|
||||||
targetRoot, multiselect, cb);
|
|
||||||
|
|
||||||
// if we have some predicates then add it to the where clause of the
|
// if we have some predicates then add it to the where clause of the
|
||||||
// multiselect
|
// multiselect
|
||||||
@@ -905,8 +903,7 @@ public class TargetManagement {
|
|||||||
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name),
|
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name),
|
||||||
targetRoot.get(pageRequest.getSort().iterator().next().getProperty()));
|
targetRoot.get(pageRequest.getSort().iterator().next().getProperty()));
|
||||||
|
|
||||||
final Specification<Target> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class,
|
final Specification<Target> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class);
|
||||||
entityManager);
|
|
||||||
final List<Specification<Target>> specList = new ArrayList<>();
|
final List<Specification<Target>> specList = new ArrayList<>();
|
||||||
specList.add(spec);
|
specList.add(spec);
|
||||||
|
|
||||||
@@ -1003,8 +1000,7 @@ public class TargetManagement {
|
|||||||
* to be created.
|
* to be created.
|
||||||
* @return the created {@link Target}s
|
* @return the created {@link Target}s
|
||||||
*
|
*
|
||||||
* @throws {@link
|
* @throws {@link EntityAlreadyExistsException} of one of the given targets
|
||||||
* EntityAlreadyExistsException} of one of the given targets
|
|
||||||
* already exist.
|
* already exist.
|
||||||
*/
|
*/
|
||||||
@Modifying
|
@Modifying
|
||||||
@@ -1012,8 +1008,8 @@ public class TargetManagement {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
|
||||||
public List<Target> createTargets(@NotNull final List<Target> targets) {
|
public List<Target> createTargets(@NotNull final List<Target> targets) {
|
||||||
if (targetRepository.countByControllerIdIn(
|
if (targetRepository.countByControllerIdIn(targets.stream().map(target -> target.getControllerId())
|
||||||
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList())) > 0) {
|
.collect(Collectors.toList())) > 0) {
|
||||||
throw new EntityAlreadyExistsException();
|
throw new EntityAlreadyExistsException();
|
||||||
}
|
}
|
||||||
final List<Target> savedTargets = new ArrayList<>();
|
final List<Target> savedTargets = new ArrayList<>();
|
||||||
@@ -1045,8 +1041,8 @@ public class TargetManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
|
||||||
public List<Target> createTargets(@NotNull final Collection<Target> targets,
|
public List<Target> createTargets(@NotNull final Collection<Target> targets,
|
||||||
@NotNull final TargetUpdateStatus status, final long lastTargetQuery, final URI address) {
|
@NotNull final TargetUpdateStatus status, final long lastTargetQuery, final URI address) {
|
||||||
if (targetRepository.countByControllerIdIn(
|
if (targetRepository.countByControllerIdIn(targets.stream().map(target -> target.getControllerId())
|
||||||
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList())) > 0) {
|
.collect(Collectors.toList())) > 0) {
|
||||||
throw new EntityAlreadyExistsException();
|
throw new EntityAlreadyExistsException();
|
||||||
}
|
}
|
||||||
final List<Target> savedTargets = new ArrayList<>();
|
final List<Target> savedTargets = new ArrayList<>();
|
||||||
@@ -1080,8 +1076,7 @@ public class TargetManagement {
|
|||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
public Long countTargetByTargetFilterQuery(@NotNull final TargetFilterQuery targetFilterQuery) {
|
public Long countTargetByTargetFilterQuery(@NotNull final TargetFilterQuery targetFilterQuery) {
|
||||||
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class,
|
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class);
|
||||||
entityManager);
|
|
||||||
return targetRepository.count(specs);
|
return targetRepository.count(specs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1094,7 +1089,7 @@ public class TargetManagement {
|
|||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
public Long countTargetByTargetFilterQuery(@NotNull final String targetFilterQuery) {
|
public Long countTargetByTargetFilterQuery(@NotNull final String targetFilterQuery) {
|
||||||
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class, entityManager);
|
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class);
|
||||||
return targetRepository.count(specs);
|
return targetRepository.count(specs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.rsql;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -19,18 +18,13 @@ import java.util.stream.Collectors;
|
|||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.MapJoin;
|
||||||
import javax.persistence.criteria.Path;
|
import javax.persistence.criteria.Path;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
|
|
||||||
import javax.persistence.metamodel.ManagedType;
|
|
||||||
import javax.persistence.metamodel.Metamodel;
|
|
||||||
import javax.persistence.metamodel.PluralAttribute;
|
|
||||||
|
|
||||||
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.model.DistributionSet;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
@@ -104,20 +98,18 @@ 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 EntityManager entityManager) {
|
final Class<A> fieldNameProvider) {
|
||||||
return new RSQLSpecification<>(rsql, fieldNameProvider, entityManager);
|
return new RSQLSpecification<>(rsql, fieldNameProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class RSQLSpecification<A extends Enum<A> & FieldNameProvider, T> implements Specification<T> {
|
private static final class RSQLSpecification<A extends Enum<A> & FieldNameProvider, T> implements Specification<T> {
|
||||||
|
|
||||||
private final String rsql;
|
private final String rsql;
|
||||||
private final Class<A> enumType;
|
private final Class<A> enumType;
|
||||||
private final EntityManager entityManager;
|
|
||||||
|
|
||||||
private RSQLSpecification(final String rsql, final Class<A> enumType, final EntityManager entityManager) {
|
private RSQLSpecification(final String rsql, final Class<A> enumType) {
|
||||||
this.rsql = rsql;
|
this.rsql = rsql;
|
||||||
this.enumType = enumType;
|
this.enumType = enumType;
|
||||||
this.entityManager = entityManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -141,8 +133,7 @@ public final class RSQLUtility {
|
|||||||
throw new RSQLParameterSyntaxException(e);
|
throw new RSQLParameterSyntaxException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
final JpqQueryRSQLVisitor<A, T> jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType,
|
final JpqQueryRSQLVisitor<A, T> jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType);
|
||||||
entityManager);
|
|
||||||
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()) {
|
||||||
@@ -169,36 +160,14 @@ public final class RSQLUtility {
|
|||||||
RSQLVisitor<List<Predicate>, String> {
|
RSQLVisitor<List<Predicate>, String> {
|
||||||
public static final Character LIKE_WILDCARD = '*';
|
public static final Character LIKE_WILDCARD = '*';
|
||||||
|
|
||||||
static {
|
|
||||||
/**
|
|
||||||
* Property mapping are done in FieldNameProvider like
|
|
||||||
* TargetFields,SoftwareModuleFields etc.
|
|
||||||
*
|
|
||||||
* In addition to this mapping in PropertyMapper are done if we want
|
|
||||||
* to drill down on entity .
|
|
||||||
*
|
|
||||||
* For example : Drill down on distribution set of target entity are
|
|
||||||
* done by adding the mappings in PropertyMapper as below.
|
|
||||||
*
|
|
||||||
* User can now use assignedds.name and assignedds.version
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
PropertyMapper.addNewMapping(Target.class, "assignedds", "assignedDistributionSet");
|
|
||||||
PropertyMapper.addNewMapping(DistributionSet.class, "name", "name");
|
|
||||||
PropertyMapper.addNewMapping(DistributionSet.class, "version", "version");
|
|
||||||
}
|
|
||||||
|
|
||||||
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 EntityManager entityManager;
|
|
||||||
|
|
||||||
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) {
|
||||||
final EntityManager entityManager) {
|
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.cb = cb;
|
this.cb = cb;
|
||||||
this.enumType = enumType;
|
this.enumType = enumType;
|
||||||
this.entityManager = entityManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -219,134 +188,146 @@ public final class RSQLUtility {
|
|||||||
return toSingleList(cb.conjunction());
|
return toSingleList(cb.conjunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> boolean isItAssociationType(final String property, final ManagedType<T> classMetadata) {
|
private List<Predicate> toSingleList(final Predicate predicate) {
|
||||||
return classMetadata.getAttribute(property).isAssociation();
|
return Collections.singletonList(predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Class<?> getPropertyType(final String property, final ManagedType<T> classMetadata) {
|
private String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
|
||||||
Class<?> propertyType;
|
String finalProperty = propertyEnum.getFieldName();
|
||||||
if (classMetadata.getAttribute(property).isCollection()) {
|
final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
||||||
propertyType = ((PluralAttribute) classMetadata.getAttribute(property)).getBindableJavaType();
|
|
||||||
} else {
|
validateMapParamter(propertyEnum, node, graph);
|
||||||
propertyType = classMetadata.getAttribute(property).getJavaType();
|
|
||||||
|
// sub entity need minium 1 dot
|
||||||
|
if (!propertyEnum.getSubEntityAttributes().isEmpty()) {
|
||||||
|
if (graph.length < 2) {
|
||||||
|
throw createRSQLParameterUnsupportedException(node);
|
||||||
}
|
}
|
||||||
return propertyType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ManagedType<?> getClassMetaData(final String property, final ManagedType classMetadata,
|
for (int i = 1; i < graph.length; i++) {
|
||||||
final Metamodel metaModel) {
|
final String propertyField = graph[i];
|
||||||
if (isItAssociationType(property, classMetadata)) {
|
finalProperty += FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + propertyField;
|
||||||
final Class<?> associationType = getPropertyType(property, classMetadata);
|
|
||||||
return metaModel.managedType(associationType);
|
// the key of map is not in the graph
|
||||||
} else {
|
if (propertyEnum.isMap() && graph.length == (i + 1)) {
|
||||||
if (isItEmbeddedType(property, classMetadata)) {
|
continue;
|
||||||
final Class<?> embeddedType = getPropertyType(property, classMetadata);
|
|
||||||
return metaModel.managedType(embeddedType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return classMetadata;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> boolean isItEmbeddedType(final String property, final ManagedType<T> classMetadata) {
|
if (!propertyEnum.containsSubEntityAttribute(propertyField)) {
|
||||||
return classMetadata.getAttribute(property).getPersistentAttributeType() == PersistentAttributeType.EMBEDDED;
|
throw createRSQLParameterUnsupportedException(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String validatePropertyFieldName(final String propertyFieldName, final boolean isDefinedInEnum,
|
|
||||||
ManagedType classMetadata, final Metamodel metaModel, final ComparisonNode node) {
|
|
||||||
String finalProperty = propertyFieldName;
|
|
||||||
final String[] graph = propertyFieldName.split("\\.");
|
|
||||||
for (String property : graph) {
|
|
||||||
if (!isDefinedInEnum && PropertyMapper.getAllowedcolmns().containsKey(classMetadata.getJavaType())) {
|
|
||||||
if (PropertyMapper.getAllowedcolmns().get(classMetadata.getJavaType()).get(property) != null) {
|
|
||||||
final String mappedValue = PropertyMapper.getAllowedcolmns().get(classMetadata.getJavaType())
|
|
||||||
.get(property);
|
|
||||||
finalProperty = finalProperty.replace(property, mappedValue);
|
|
||||||
property = mappedValue;
|
|
||||||
} else {
|
|
||||||
throw new RSQLParameterUnsupportedFieldException("The given search parameter field {"
|
|
||||||
+ node.getSelector() + "} does not exist, must be one of the following fields {"
|
|
||||||
+ getExpectedFieldList() + "}", new Exception());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
classMetadata = getClassMetaData(property, classMetadata, metaModel);
|
|
||||||
}
|
|
||||||
return finalProperty;
|
return finalProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path<Object> getFieldPath(final String finalProperty) {
|
private void validateMapParamter(final A propertyEnum, final ComparisonNode node, final String[] graph) {
|
||||||
|
if (!propertyEnum.isMap()) {
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!propertyEnum.getSubEntityAttributes().isEmpty()) {
|
||||||
|
throw new UnsupportedOperationException("Currently subentity attributes for maps are not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// enum.key
|
||||||
|
final int minAttributeForMap = 2;
|
||||||
|
if (graph.length != minAttributeForMap) {
|
||||||
|
throw new RSQLParameterUnsupportedFieldException("The syntax of the given map search parameter field {"
|
||||||
|
+ node.getSelector() + "} is wrong. Syntax is: fieldname.keyname", new Exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(final ComparisonNode node) {
|
||||||
|
return new RSQLParameterUnsupportedFieldException("The given search parameter field {" + node.getSelector()
|
||||||
|
+ "} does not exist, must be one of the following fields {" + getExpectedFieldList() + "}",
|
||||||
|
new Exception());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path<Object> getFieldPath(final A enumField, final String finalProperty) {
|
||||||
Path<Object> fieldPath = null;
|
Path<Object> fieldPath = null;
|
||||||
final String[] split = finalProperty.split("\\.");
|
final String[] split = finalProperty.split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
||||||
if (split.length == 0) {
|
if (split.length == 0) {
|
||||||
fieldPath = root.get(split[0]);
|
return root.get(split[0]);
|
||||||
} else {
|
}
|
||||||
for (final String fieldNameSplit : split) {
|
|
||||||
// hibernate workaround because cannot get attribute of an
|
for (int i = 0; i < split.length; i++) {
|
||||||
// PluralAttributePath, needs
|
final boolean isMapKeyField = enumField.isMap() && i == (split.length - 1);
|
||||||
// an implicit join.
|
if (isMapKeyField) {
|
||||||
// https://hibernate.atlassian.net/browse/HHH-7892
|
return fieldPath;
|
||||||
if (fieldPath == null && root.get(fieldNameSplit) != null
|
}
|
||||||
&& Collection.class.isAssignableFrom(root.get(fieldNameSplit).getJavaType())) {
|
|
||||||
fieldPath = root.join(fieldNameSplit);
|
final String fieldNameSplit = split[i];
|
||||||
} else {
|
|
||||||
fieldPath = (fieldPath != null) ? fieldPath.get(fieldNameSplit) : root.get(fieldNameSplit);
|
fieldPath = (fieldPath != null) ? fieldPath.get(fieldNameSplit) : root.get(fieldNameSplit);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return fieldPath;
|
return fieldPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Predicate> visit(final ComparisonNode node, final String param) {
|
public List<Predicate> visit(final ComparisonNode node, final String param) {
|
||||||
final Metamodel metaModel = entityManager.getMetamodel();
|
|
||||||
final ManagedType<?> classMetadata = metaModel.managedType(root.getJavaType());
|
|
||||||
String propertyFieldName = null;
|
|
||||||
Boolean isDefinedInEnum = Boolean.FALSE;
|
|
||||||
A fieldName = null;
|
A fieldName = null;
|
||||||
try {
|
try {
|
||||||
/**
|
fieldName = getFieldEnumByName(node);
|
||||||
* Get the property mapping from FieldNameProvider .If not
|
|
||||||
* available check in PropertyMapping.If not found throw
|
|
||||||
* RSQLParameterUnsupportedFieldException.
|
|
||||||
*/
|
|
||||||
fieldName = getFieldIdentifierByName(node);
|
|
||||||
propertyFieldName = fieldName.getFieldName();
|
|
||||||
isDefinedInEnum = Boolean.TRUE;
|
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
if (PropertyMapper.getAllowedcolmns().containsKey(classMetadata.getJavaType())) {
|
|
||||||
propertyFieldName = node.getSelector();
|
|
||||||
} else {
|
|
||||||
throw new RSQLParameterUnsupportedFieldException("The given search parameter field {"
|
throw new RSQLParameterUnsupportedFieldException("The given search parameter field {"
|
||||||
+ node.getSelector()
|
+ node.getSelector()
|
||||||
+ "} does not exist, must be one of the following fields {"
|
+ "} does not exist, must be one of the following fields {"
|
||||||
+ Arrays.stream(enumType.getEnumConstants()).map(v -> v.name().toLowerCase())
|
+ Arrays.stream(enumType.getEnumConstants()).map(v -> v.name().toLowerCase())
|
||||||
.collect(Collectors.toList()) + "}", e);
|
.collect(Collectors.toList()) + "}", e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
final String finalProperty = getAndValidatePropertyFieldName(fieldName, node);
|
||||||
final String finalProperty = validatePropertyFieldName(propertyFieldName, isDefinedInEnum, classMetadata,
|
|
||||||
metaModel, node);
|
|
||||||
|
|
||||||
final List<String> values = node.getArguments();
|
final List<String> values = node.getArguments();
|
||||||
final List<Object> transformedValue = new ArrayList<>();
|
final List<Object> transformedValue = new ArrayList<>();
|
||||||
final Path<Object> fieldPath = getFieldPath(finalProperty);
|
final Path<Object> fieldPath = getFieldPath(fieldName, finalProperty);
|
||||||
|
|
||||||
for (final String value : values) {
|
for (final String value : values) {
|
||||||
transformedValue.add(convertValueIfNecessary(node, fieldName, value, fieldPath));
|
transformedValue.add(convertValueIfNecessary(node, fieldName, value, fieldPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapToPredicate(node, fieldPath, node.getArguments(), transformedValue);
|
return mapToPredicate(node, fieldPath, node.getArguments(), transformedValue, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getExpectedFieldList() {
|
private List<String> getExpectedFieldList() {
|
||||||
final List<String> expectedFieldList = Arrays.stream(enumType.getEnumConstants())
|
final List<String> expectedFieldList = Arrays.stream(enumType.getEnumConstants())
|
||||||
.map(v -> v.name().toLowerCase()).collect(Collectors.toList());
|
.filter(enumField -> enumField.getSubEntityAttributes().isEmpty()).map(enumField -> {
|
||||||
expectedFieldList.add("assignedds.name");
|
final String enumFieldName = enumField.name().toLowerCase();
|
||||||
expectedFieldList.add("assignedds.version");
|
|
||||||
|
if (enumField.isMap()) {
|
||||||
|
return enumFieldName + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + "keyName";
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumFieldName;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<String> expectedSubFieldList = Arrays
|
||||||
|
.stream(enumType.getEnumConstants())
|
||||||
|
.filter(enumField -> !enumField.getSubEntityAttributes().isEmpty())
|
||||||
|
.flatMap(
|
||||||
|
enumField -> {
|
||||||
|
final List<String> subEntity = enumField
|
||||||
|
.getSubEntityAttributes()
|
||||||
|
.stream()
|
||||||
|
.map(fieldName -> enumField.name().toLowerCase()
|
||||||
|
+ FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + fieldName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return subEntity.stream();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
expectedFieldList.addAll(expectedSubFieldList);
|
||||||
return expectedFieldList;
|
return expectedFieldList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private A getFieldIdentifierByName(final ComparisonNode node) {
|
private A getFieldEnumByName(final ComparisonNode node) {
|
||||||
final String enumName = node.getSelector().toUpperCase();
|
String enumName = node.getSelector();
|
||||||
|
final String[] graph = enumName.split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
||||||
|
if (graph.length != 0) {
|
||||||
|
enumName = graph[0];
|
||||||
|
}
|
||||||
LOGGER.debug("get fieldidentifier by name {} of enum type {}", enumName, enumType);
|
LOGGER.debug("get fieldidentifier by name {} of enum type {}", enumName, enumType);
|
||||||
return Enum.valueOf(enumType, enumName);
|
return Enum.valueOf(enumType, enumName.toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@@ -400,58 +381,86 @@ public final class RSQLUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Predicate> mapToPredicate(final ComparisonNode node, final Path<Object> fieldPath,
|
private List<Predicate> mapToPredicate(final ComparisonNode node, Path<Object> fieldPath,
|
||||||
final List<String> values, final List<Object> transformedValues) {
|
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 methods.
|
// cannot handle object types for greaterThan etc methods.
|
||||||
final Object transformedValue = transformedValues.get(0);
|
final Object transformedValue = transformedValues.get(0);
|
||||||
final String value = values.get(0);
|
final String value = values.get(0);
|
||||||
final List<Predicate> singleList;
|
final List<Predicate> singleList = new ArrayList<>();
|
||||||
|
|
||||||
|
final Predicate mapPredicate = mapToMapPredicate(node, fieldPath, enumField);
|
||||||
|
if (mapPredicate != null) {
|
||||||
|
singleList.add(mapPredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldPath = getMapValueFieldPath(enumField, fieldPath);
|
||||||
|
|
||||||
switch (node.getOperator().getSymbol()) {
|
switch (node.getOperator().getSymbol()) {
|
||||||
case "=li=":
|
case "=li=":
|
||||||
singleList = toSingleList(cb.like(cb.upper(pathOfString(fieldPath)), transformedValue.toString()
|
singleList.add(cb.like(cb.upper(pathOfString(fieldPath)), transformedValue.toString().toUpperCase()));
|
||||||
.toUpperCase()));
|
|
||||||
break;
|
break;
|
||||||
case "==":
|
case "==":
|
||||||
singleList = getEqualToPredicate(transformedValue, fieldPath);
|
singleList.add(getEqualToPredicate(transformedValue, fieldPath));
|
||||||
break;
|
break;
|
||||||
case "!=":
|
case "!=":
|
||||||
singleList = toSingleList(cb.notEqual(fieldPath, transformedValue));
|
singleList.add(cb.notEqual(fieldPath, transformedValue));
|
||||||
break;
|
break;
|
||||||
case "=gt=":
|
case "=gt=":
|
||||||
singleList = toSingleList(cb.greaterThan(pathOfString(fieldPath), value));
|
singleList.add(cb.greaterThan(pathOfString(fieldPath), value));
|
||||||
break;
|
break;
|
||||||
case "=ge=":
|
case "=ge=":
|
||||||
singleList = toSingleList(cb.greaterThanOrEqualTo(pathOfString(fieldPath), value));
|
singleList.add(cb.greaterThanOrEqualTo(pathOfString(fieldPath), value));
|
||||||
break;
|
break;
|
||||||
case "=lt=":
|
case "=lt=":
|
||||||
singleList = toSingleList(cb.lessThan(pathOfString(fieldPath), value));
|
singleList.add(cb.lessThan(pathOfString(fieldPath), value));
|
||||||
break;
|
break;
|
||||||
case "=le=":
|
case "=le=":
|
||||||
singleList = toSingleList(cb.lessThanOrEqualTo(pathOfString(fieldPath), value));
|
singleList.add(cb.lessThanOrEqualTo(pathOfString(fieldPath), value));
|
||||||
break;
|
break;
|
||||||
case "=in=":
|
case "=in=":
|
||||||
singleList = toSingleList(fieldPath.in(transformedValues));
|
singleList.add(fieldPath.in(transformedValues));
|
||||||
break;
|
break;
|
||||||
case "=out=":
|
case "=out=":
|
||||||
singleList = toSingleList(cb.not(fieldPath.in(transformedValues)));
|
singleList.add(cb.not(fieldPath.in(transformedValues)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGGER.info("operator symbol {} is either not supported or not implemented");
|
LOGGER.info("operator symbol {} is either not supported or not implemented");
|
||||||
singleList = Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
return singleList;
|
return Collections.unmodifiableList(singleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Predicate> getEqualToPredicate(final Object transformedValue, final Path<Object> fieldPath) {
|
/**
|
||||||
|
* @param enumField
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Path<Object> getMapValueFieldPath(final A enumField, final Path<Object> fieldPath) {
|
||||||
|
if (!enumField.isMap() || enumField.getValueFieldName() == null) {
|
||||||
|
return fieldPath;
|
||||||
|
}
|
||||||
|
return fieldPath.get(enumField.getValueFieldName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Predicate mapToMapPredicate(final ComparisonNode node, final Path<Object> fieldPath, final A enumField) {
|
||||||
|
if (!enumField.isMap()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
||||||
|
final String keyValue = graph[graph.length - 1];
|
||||||
|
if (fieldPath instanceof MapJoin) {
|
||||||
|
return cb.equal(((MapJoin) fieldPath).key(), keyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb.equal(fieldPath.get(enumField.getKeyFieldName()), keyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Predicate getEqualToPredicate(final Object transformedValue, final Path<Object> fieldPath) {
|
||||||
if (transformedValue instanceof String) {
|
if (transformedValue instanceof String) {
|
||||||
final String preFormattedValue = ((String) transformedValue).replace(LIKE_WILDCARD, '%');
|
final String preFormattedValue = ((String) transformedValue).replace(LIKE_WILDCARD, '%');
|
||||||
return toSingleList(cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toString()
|
return cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toString().toUpperCase());
|
||||||
.toUpperCase()));
|
|
||||||
} else {
|
|
||||||
return toSingleList(cb.equal(fieldPath, transformedValue));
|
|
||||||
}
|
}
|
||||||
|
return cb.equal(fieldPath, transformedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -473,8 +482,5 @@ public final class RSQLUtility {
|
|||||||
return childs;
|
return childs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Predicate> toSingleList(final Predicate p) {
|
|
||||||
return Collections.singletonList(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ public class DistributionSetResource {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DistributionSetManagement distributionSetManagement;
|
private DistributionSetManagement distributionSetManagement;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving all {@link DistributionSet}s within
|
* Handles the GET request of retrieving all {@link DistributionSet}s within
|
||||||
@@ -130,7 +128,7 @@ public class DistributionSetResource {
|
|||||||
final Page<DistributionSet> findDsPage;
|
final Page<DistributionSet> findDsPage;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
findDsPage = distributionSetManagement.findDistributionSetsAll(
|
findDsPage = distributionSetManagement.findDistributionSetsAll(
|
||||||
RSQLUtility.parse(rsqlParam, DistributionSetFields.class, entityManager), pageable, false);
|
RSQLUtility.parse(rsqlParam, DistributionSetFields.class), pageable, false);
|
||||||
} else {
|
} else {
|
||||||
findDsPage = distributionSetManagement.findDistributionSetsAll(pageable, false, null);
|
findDsPage = distributionSetManagement.findDistributionSetsAll(pageable, false, null);
|
||||||
}
|
}
|
||||||
@@ -281,7 +279,7 @@ public class DistributionSetResource {
|
|||||||
final Page<Target> targetsAssignedDS;
|
final Page<Target> targetsAssignedDS;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId,
|
targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId,
|
||||||
RSQLUtility.parse(rsqlParam, TargetFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
|
||||||
} else {
|
} else {
|
||||||
targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId, pageable);
|
targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId, pageable);
|
||||||
}
|
}
|
||||||
@@ -331,7 +329,7 @@ public class DistributionSetResource {
|
|||||||
final Page<Target> targetsInstalledDS;
|
final Page<Target> targetsInstalledDS;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId,
|
targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId,
|
||||||
RSQLUtility.parse(rsqlParam, TargetFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
|
||||||
} else {
|
} else {
|
||||||
targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId, pageable);
|
targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId, pageable);
|
||||||
}
|
}
|
||||||
@@ -410,7 +408,7 @@ public class DistributionSetResource {
|
|||||||
|
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
|
metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
|
||||||
RSQLUtility.parse(rsqlParam, DistributionSetMetadataFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, DistributionSetMetadataFields.class), pageable);
|
||||||
} else {
|
} else {
|
||||||
metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
|
metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
|
||||||
pageable);
|
pageable);
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ public class DistributionSetTagResource {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DistributionSetManagement distributionSetManagement;
|
private DistributionSetManagement distributionSetManagement;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving all DistributionSet tags.
|
* Handles the GET request of retrieving all DistributionSet tags.
|
||||||
@@ -103,7 +101,7 @@ public class DistributionSetTagResource {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
final Page<DistributionSetTag> findTargetPage = tagManagement.findAllDistributionSetTags(
|
final Page<DistributionSetTag> findTargetPage = tagManagement.findAllDistributionSetTags(
|
||||||
RSQLUtility.parse(rsqlParam, TagFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, TagFields.class), pageable);
|
||||||
countTargetsAll = findTargetPage.getTotalElements();
|
countTargetsAll = findTargetPage.getTotalElements();
|
||||||
findTargetsAll = findTargetPage;
|
findTargetsAll = findTargetPage;
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,6 @@ public class DistributionSetTypeResource {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DistributionSetManagement distributionSetManagement;
|
private DistributionSetManagement distributionSetManagement;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the GET request of retrieving all {@link DistributionSetType}s
|
* Handles the GET request of retrieving all {@link DistributionSetType}s
|
||||||
* within SP.
|
* within SP.
|
||||||
@@ -105,7 +102,7 @@ public class DistributionSetTypeResource {
|
|||||||
Long countModulesAll;
|
Long countModulesAll;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
findModuleTypessAll = distributionSetManagement.findDistributionSetTypesByPredicate(
|
findModuleTypessAll = distributionSetManagement.findDistributionSetTypesByPredicate(
|
||||||
RSQLUtility.parse(rsqlParam, DistributionSetTypeFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, DistributionSetTypeFields.class), pageable);
|
||||||
countModulesAll = ((Page<DistributionSetType>) findModuleTypessAll).getTotalElements();
|
countModulesAll = ((Page<DistributionSetType>) findModuleTypessAll).getTotalElements();
|
||||||
} else {
|
} else {
|
||||||
findModuleTypessAll = distributionSetManagement.findDistributionSetTypesAll(pageable);
|
findModuleTypessAll = distributionSetManagement.findDistributionSetTypesAll(pageable);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.rest.resource;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@@ -75,9 +74,6 @@ public class SoftwareModuleResource {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SoftwareManagement softwareManagement;
|
private SoftwareManagement softwareManagement;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles POST request for artifact upload.
|
* Handles POST request for artifact upload.
|
||||||
*
|
*
|
||||||
@@ -266,7 +262,7 @@ public class SoftwareModuleResource {
|
|||||||
Long countModulesAll;
|
Long countModulesAll;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
findModulesAll = softwareManagement.findSoftwareModulesByPredicate(
|
findModulesAll = softwareManagement.findSoftwareModulesByPredicate(
|
||||||
RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class), pageable);
|
||||||
countModulesAll = ((Page<SoftwareModule>) findModulesAll).getTotalElements();
|
countModulesAll = ((Page<SoftwareModule>) findModulesAll).getTotalElements();
|
||||||
} else {
|
} else {
|
||||||
findModulesAll = softwareManagement.findSoftwareModulesAll(pageable);
|
findModulesAll = softwareManagement.findSoftwareModulesAll(pageable);
|
||||||
@@ -307,8 +303,8 @@ public class SoftwareModuleResource {
|
|||||||
* failure the JsonResponseExceptionHandler is handling the
|
* failure the JsonResponseExceptionHandler is handling the
|
||||||
* response.
|
* response.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
|
@RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }, produces = {
|
||||||
MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
|
"application/hal+json", MediaType.APPLICATION_JSON_VALUE })
|
||||||
public ResponseEntity<SoftwareModulesRest> createSoftwareModules(
|
public ResponseEntity<SoftwareModulesRest> createSoftwareModules(
|
||||||
@RequestBody final List<SoftwareModuleRequestBodyPost> softwareModules) {
|
@RequestBody final List<SoftwareModuleRequestBodyPost> softwareModules) {
|
||||||
LOG.debug("creating {} softwareModules", softwareModules.size());
|
LOG.debug("creating {} softwareModules", softwareModules.size());
|
||||||
@@ -387,7 +383,8 @@ public class SoftwareModuleResource {
|
|||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata", produces = {
|
||||||
MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
|
MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
|
||||||
public ResponseEntity<MetadataRestPageList> getMetadata(@PathVariable final Long softwareModuleId,
|
public ResponseEntity<MetadataRestPageList> getMetadata(
|
||||||
|
@PathVariable final Long softwareModuleId,
|
||||||
@RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
@RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
||||||
@RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
@RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
|
||||||
@RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
|
@RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
|
||||||
@@ -405,15 +402,13 @@ public class SoftwareModuleResource {
|
|||||||
|
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
metaDataPage = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(softwareModuleId,
|
metaDataPage = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(softwareModuleId,
|
||||||
RSQLUtility.parse(rsqlParam, SoftwareModuleMetadataFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, SoftwareModuleMetadataFields.class), pageable);
|
||||||
} else {
|
} else {
|
||||||
metaDataPage = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(softwareModuleId, pageable);
|
metaDataPage = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(softwareModuleId, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ResponseEntity<>(
|
return new ResponseEntity<>(new MetadataRestPageList(SoftwareModuleMapper.toResponseSwMetadata(metaDataPage
|
||||||
new MetadataRestPageList(SoftwareModuleMapper.toResponseSwMetadata(metaDataPage.getContent()),
|
.getContent()), metaDataPage.getTotalElements()), HttpStatus.OK);
|
||||||
metaDataPage.getTotalElements()),
|
|
||||||
HttpStatus.OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,8 +421,7 @@ public class SoftwareModuleResource {
|
|||||||
* @return status OK if get request is successful with the value of the meta
|
* @return status OK if get request is successful with the value of the meta
|
||||||
* data
|
* data
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = {
|
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = { MediaType.APPLICATION_JSON_VALUE })
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
|
||||||
public ResponseEntity<MetadataRest> getMetadataValue(@PathVariable final Long softwareModuleId,
|
public ResponseEntity<MetadataRest> getMetadataValue(@PathVariable final Long softwareModuleId,
|
||||||
@PathVariable final String metadataKey) {
|
@PathVariable final String metadataKey) {
|
||||||
// check if distribution set exists otherwise throw exception
|
// check if distribution set exists otherwise throw exception
|
||||||
@@ -487,8 +481,8 @@ public class SoftwareModuleResource {
|
|||||||
* the created meta data
|
* the created meta data
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/metadata", consumes = {
|
@RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/metadata", consumes = {
|
||||||
MediaType.APPLICATION_JSON_VALUE,
|
MediaType.APPLICATION_JSON_VALUE, "application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE,
|
||||||
"application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
|
"application/hal+json" })
|
||||||
public ResponseEntity<List<MetadataRest>> createMetadata(@PathVariable final Long softwareModuleId,
|
public ResponseEntity<List<MetadataRest>> createMetadata(@PathVariable final Long softwareModuleId,
|
||||||
@RequestBody final List<MetadataRest> metadataRest) {
|
@RequestBody final List<MetadataRest> metadataRest) {
|
||||||
// check if software module exists otherwise throw exception immediately
|
// check if software module exists otherwise throw exception immediately
|
||||||
@@ -501,8 +495,7 @@ public class SoftwareModuleResource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SoftwareModule findSoftwareModuleWithExceptionIfNotFound(final Long softwareModuleId,
|
private SoftwareModule findSoftwareModuleWithExceptionIfNotFound(final Long softwareModuleId, final Long artifactId) {
|
||||||
final Long artifactId) {
|
|
||||||
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
|
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
throw new EntityNotFoundException("SoftwareModule with Id {" + softwareModuleId + "} does not exist");
|
throw new EntityNotFoundException("SoftwareModule with Id {" + softwareModuleId + "} does not exist");
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class SoftwareModuleTypeResource {
|
|||||||
Long countModulesAll;
|
Long countModulesAll;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
findModuleTypessAll = softwareManagement.findSoftwareModuleTypesByPredicate(
|
findModuleTypessAll = softwareManagement.findSoftwareModuleTypesByPredicate(
|
||||||
RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class), pageable);
|
||||||
countModulesAll = ((Page<SoftwareModuleType>) findModuleTypessAll).getTotalElements();
|
countModulesAll = ((Page<SoftwareModuleType>) findModuleTypessAll).getTotalElements();
|
||||||
} else {
|
} else {
|
||||||
findModuleTypessAll = softwareManagement.findSoftwareModuleTypesAll(pageable);
|
findModuleTypessAll = softwareManagement.findSoftwareModuleTypesAll(pageable);
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class TargetResource {
|
|||||||
final Long countTargetsAll;
|
final Long countTargetsAll;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
final Page<Target> findTargetPage = targetManagement.findTargetsAll(
|
final Page<Target> findTargetPage = targetManagement.findTargetsAll(
|
||||||
RSQLUtility.parse(rsqlParam, TargetFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
|
||||||
countTargetsAll = findTargetPage.getTotalElements();
|
countTargetsAll = findTargetPage.getTotalElements();
|
||||||
findTargetsAll = findTargetPage;
|
findTargetsAll = findTargetPage;
|
||||||
} else {
|
} else {
|
||||||
@@ -284,7 +284,7 @@ public class TargetResource {
|
|||||||
final Slice<Action> activeActions;
|
final Slice<Action> activeActions;
|
||||||
final Long totalActionCount;
|
final Long totalActionCount;
|
||||||
if (rsqlParam != null) {
|
if (rsqlParam != null) {
|
||||||
final Specification<Action> parse = RSQLUtility.parse(rsqlParam, ActionFields.class, entityManager);
|
final Specification<Action> parse = RSQLUtility.parse(rsqlParam, ActionFields.class);
|
||||||
activeActions = deploymentManagement.findActionsByTarget(parse, foundTarget, pageable);
|
activeActions = deploymentManagement.findActionsByTarget(parse, foundTarget, pageable);
|
||||||
totalActionCount = deploymentManagement.countActionsByTarget(parse, foundTarget);
|
totalActionCount = deploymentManagement.countActionsByTarget(parse, foundTarget);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class TargetTagResource {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
final Page<TargetTag> findTargetPage = tagManagement.findAllTargetTags(
|
final Page<TargetTag> findTargetPage = tagManagement.findAllTargetTags(
|
||||||
RSQLUtility.parse(rsqlParam, TagFields.class, entityManager), pageable);
|
RSQLUtility.parse(rsqlParam, TagFields.class), pageable);
|
||||||
countTargetsAll = findTargetPage.getTotalElements();
|
countTargetsAll = findTargetPage.getTotalElements();
|
||||||
findTargetsAll = findTargetPage;
|
findTargetsAll = findTargetPage;
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,12 @@ import static org.junit.Assert.fail;
|
|||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Expression;
|
import javax.persistence.criteria.Expression;
|
||||||
@@ -27,11 +25,11 @@ import javax.persistence.criteria.Path;
|
|||||||
import javax.persistence.criteria.Predicate;
|
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 javax.persistence.metamodel.ManagedType;
|
|
||||||
import javax.persistence.metamodel.Metamodel;
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
import org.eclipse.hawkbit.repository.TargetFields;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.rsql.RSQLParameterSyntaxException;
|
import org.eclipse.hawkbit.repository.rsql.RSQLParameterSyntaxException;
|
||||||
import org.eclipse.hawkbit.repository.rsql.RSQLParameterUnsupportedFieldException;
|
import org.eclipse.hawkbit.repository.rsql.RSQLParameterUnsupportedFieldException;
|
||||||
@@ -39,9 +37,7 @@ import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Features;
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
import ru.yandex.qatools.allure.annotations.Stories;
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
@@ -60,33 +56,87 @@ public class RSQLUtilityTest {
|
|||||||
private CriteriaQuery<SoftwareModule> criteriaQueryMock;
|
private CriteriaQuery<SoftwareModule> criteriaQueryMock;
|
||||||
@Mock
|
@Mock
|
||||||
private CriteriaBuilder criteriaBuilderMock;
|
private CriteriaBuilder criteriaBuilderMock;
|
||||||
@Mock
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private Metamodel metamodel;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private ManagedType managedType;
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Attribute attribute;
|
private Attribute attribute;
|
||||||
|
|
||||||
@Test(expected = RSQLParameterSyntaxException.class)
|
@Test
|
||||||
public void wrongRsqlSyntaxThrowSyntaxException() {
|
public void wrongRsqlSyntaxThrowSyntaxException() {
|
||||||
final String wrongRSQL = "name==abc;d";
|
final String wrongRSQL = "name==abc;d";
|
||||||
when(entityManager.getMetamodel()).thenReturn(metamodel);
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterSyntaxException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = RSQLParameterUnsupportedFieldException.class)
|
@Test
|
||||||
public void wrongFieldThrowUnsupportedFieldException() {
|
public void wrongFieldThrowUnsupportedFieldException() {
|
||||||
final String wrongRSQL = "unknownField==abc";
|
final String wrongRSQL = "unknownField==abc";
|
||||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||||
doEntitySetup(SoftwareModule.class);
|
try {
|
||||||
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void wrongRsqlMapSyntaxThrowSyntaxException() {
|
||||||
|
String wrongRSQL = TargetFields.ATTRIBUTE + "==abc";
|
||||||
|
try {
|
||||||
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
|
criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
wrongRSQL = TargetFields.ATTRIBUTE + ".unkwon.wrong==abc";
|
||||||
|
try {
|
||||||
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
|
criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
wrongRSQL = DistributionSetFields.METADATA + "==abc";
|
||||||
|
try {
|
||||||
|
RSQLUtility.parse(wrongRSQL, DistributionSetFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void wrongRsqlSubEntitySyntaxThrowSyntaxException() {
|
||||||
|
String wrongRSQL = TargetFields.ASSIGNEDDS + "==abc";
|
||||||
|
try {
|
||||||
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
|
criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
wrongRSQL = TargetFields.ASSIGNEDDS + ".unknownField==abc";
|
||||||
|
try {
|
||||||
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
|
criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
wrongRSQL = TargetFields.ASSIGNEDDS + ".unknownField.ToMuch==abc";
|
||||||
|
try {
|
||||||
|
RSQLUtility.parse(wrongRSQL, TargetFields.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
|
criteriaBuilderMock);
|
||||||
|
fail();
|
||||||
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -100,11 +150,9 @@ public class RSQLUtilityTest {
|
|||||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
|
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
|
||||||
mock(Predicate.class));
|
mock(Predicate.class));
|
||||||
|
|
||||||
doEntitySetup(SoftwareModule.class);
|
|
||||||
|
|
||||||
// test
|
// test
|
||||||
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
|
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||||
@@ -119,10 +167,9 @@ public class RSQLUtilityTest {
|
|||||||
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
||||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
|
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
|
||||||
mock(Predicate.class));
|
mock(Predicate.class));
|
||||||
doEntitySetup(SoftwareModule.class);
|
|
||||||
// test
|
// test
|
||||||
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
|
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||||
@@ -138,10 +185,9 @@ public class RSQLUtilityTest {
|
|||||||
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
||||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
|
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
|
||||||
mock(Predicate.class));
|
mock(Predicate.class));
|
||||||
doEntitySetup(SoftwareModule.class);
|
|
||||||
// test
|
// test
|
||||||
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
|
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||||
@@ -159,10 +205,9 @@ public class RSQLUtilityTest {
|
|||||||
mock(Predicate.class));
|
mock(Predicate.class));
|
||||||
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock)))).thenReturn(
|
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock)))).thenReturn(
|
||||||
pathOfString(baseSoftwareModuleRootMock));
|
pathOfString(baseSoftwareModuleRootMock));
|
||||||
doEntitySetup(SoftwareModule.class);
|
|
||||||
// test
|
// test
|
||||||
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
|
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||||
@@ -178,10 +223,9 @@ public class RSQLUtilityTest {
|
|||||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
|
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
|
||||||
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
||||||
|
|
||||||
doEntitySetup(TestValueEnum.class);
|
|
||||||
// test
|
// test
|
||||||
RSQLUtility.parse(correctRsql, TestFieldEnum.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(correctRsql, TestFieldEnum.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaBuilderMock);
|
||||||
|
|
||||||
// verfication
|
// verfication
|
||||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||||
@@ -196,11 +240,9 @@ public class RSQLUtilityTest {
|
|||||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
|
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
|
||||||
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
|
||||||
|
|
||||||
doEntitySetup(TestValueEnum.class);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// test
|
// test
|
||||||
RSQLUtility.parse(correctRsql, TestFieldEnum.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
|
RSQLUtility.parse(correctRsql, TestFieldEnum.class).toPredicate(baseSoftwareModuleRootMock,
|
||||||
criteriaQueryMock, criteriaBuilderMock);
|
criteriaQueryMock, criteriaBuilderMock);
|
||||||
fail("missing RSQLParameterUnsupportedFieldException for wrong enum value");
|
fail("missing RSQLParameterUnsupportedFieldException for wrong enum value");
|
||||||
} catch (final RSQLParameterUnsupportedFieldException e) {
|
} catch (final RSQLParameterUnsupportedFieldException e) {
|
||||||
@@ -208,22 +250,6 @@ public class RSQLUtilityTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doEntitySetup(final Class clasName) {
|
|
||||||
when(entityManager.getMetamodel()).thenReturn(metamodel);
|
|
||||||
when(metamodel.managedType(clasName)).thenReturn(managedType);
|
|
||||||
when(managedType.getJavaType()).thenReturn(clasName);
|
|
||||||
|
|
||||||
doAnswer(new Answer<Attribute>() {
|
|
||||||
@Override
|
|
||||||
public Attribute answer(final InvocationOnMock invocation) throws Throwable {
|
|
||||||
return attribute;
|
|
||||||
}
|
|
||||||
}).when(managedType).getAttribute(anyString());
|
|
||||||
|
|
||||||
when(attribute.isAssociation()).thenReturn(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <Y> Path<Y> pathOfString(final Path<?> path) {
|
private <Y> Path<Y> pathOfString(final Path<?> path) {
|
||||||
return (Path<Y>) path;
|
return (Path<Y>) path;
|
||||||
|
|||||||
Reference in New Issue
Block a user