Merge pull request #9 from bsinno/MECS-1438_CREATE_FILTER_OPTIONS_FOR_MAP

ok
This commit is contained in:
Kai Zimmermann
2016-01-26 11:35:53 +01:00
14 changed files with 466 additions and 284 deletions

View File

@@ -36,16 +36,50 @@ public enum DistributionSetFields implements FieldNameProvider {
/**
* 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 String keyFieldName;
private String valueFieldName;
private DistributionSetFields(final String fieldName) {
this(fieldName, null, null);
}
private DistributionSetFields(final String fieldName, final String keyFieldName, final String valueFieldName) {
this.fieldName = fieldName;
this.keyFieldName = keyFieldName;
this.valueFieldName = valueFieldName;
}
@Override
public String getValueFieldName() {
return valueFieldName;
}
@Override
public String getKeyFieldName() {
return keyFieldName;
}
@Override
public String getFieldName() {
return fieldName;
}
}

View File

@@ -8,18 +8,87 @@
*/
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
* which is used as string representation of the field, e.g. for sorting the
* fields over REST.
*
*/
@FunctionalInterface
public interface FieldNameProvider {
/**
* Seperator for the sub attributes
*/
public static final String SUB_ATTRIBUTE_SEPERATOR = ".";
/**
* @return the string representation of the underlying persistence field
* name e.g. in case of sorting. Never {@code null}.
*/
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;
}
}

View File

@@ -36,16 +36,38 @@ public enum SoftwareModuleFields implements FieldNameProvider {
/**
* The id field.
*/
ID("id");
ID("id"),
/**
* The metadata.
*/
METADATA("metadata", "key", "value");
private final String fieldName;
private String keyFieldName;
private String valueFieldName;
private SoftwareModuleFields(final String fieldName) {
this(fieldName, null, null);
}
private SoftwareModuleFields(final String fieldName, final String keyFieldName, final String valueFieldName) {
this.fieldName = fieldName;
this.keyFieldName = keyFieldName;
this.valueFieldName = valueFieldName;
}
@Override
public String getFieldName() {
return fieldName;
}
@Override
public String getKeyFieldName() {
return keyFieldName;
}
@Override
public String getValueFieldName() {
return valueFieldName;
}
}

View File

@@ -8,15 +8,22 @@
*/
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
* e.g. for sorting etc.
*
*
*
*
*/
public enum TargetFields implements FieldNameProvider {
/**
* The controllerId field.
*/
ID("controllerId"),
/**
* The name field.
*/
@@ -37,12 +44,49 @@ public enum TargetFields implements FieldNameProvider {
/**
* 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 List<String> subEntityAttribues;
private boolean mapField;
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.mapField = mapField;
this.subEntityAttribues = subEntityAttribues;
}
@Override
public List<String> getSubEntityAttributes() {
return subEntityAttribues;
}
@Override
public boolean isMap() {
return mapField;
}
@Override

View File

@@ -205,8 +205,7 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
public Slice<Target> findTargetsAll(@NotNull final TargetFilterQuery targetFilterQuery,
@NotNull final Pageable pageable) {
return findTargetsAll(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, entityManager),
pageable);
return findTargetsAll(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class), pageable);
}
/**
@@ -220,7 +219,7 @@ public class TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
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)
public Page<Target> findTargetByAssignedDistributionSet(@NotNull final Long distributionSetID,
final Specification<Target> spec, @NotNull final Pageable pageReq) {
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(
TargetSpecifications.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb),
spec.toPredicate(root, query, cb)), pageReq);
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(TargetSpecifications
.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb), spec.toPredicate(root,
query, cb)), pageReq);
}
/**
@@ -390,9 +389,9 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
public Page<Target> findTargetByInstalledDistributionSet(final Long distributionSetId,
final Specification<Target> spec, final Pageable pageable) {
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(
TargetSpecifications.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb),
spec.toPredicate(root, query, cb)), pageable);
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(TargetSpecifications
.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb), spec.toPredicate(root,
query, cb)), pageable);
}
/**
@@ -487,8 +486,8 @@ public class TargetManagement {
specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch));
}
if (installedOrAssignedDistributionSetId != null) {
specList.add(
TargetSpecifications.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
specList.add(TargetSpecifications
.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId));
}
if (!Strings.isNullOrEmpty(searchText)) {
specList.add(TargetSpecifications.likeNameOrDescriptionOrIp(searchText));
@@ -560,8 +559,8 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
public TargetTagAssigmentResult toggleTagAssignment(@NotEmpty final List<Target> targets,
@NotNull final TargetTag tag) {
return toggleTagAssignment(
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList()), tag.getName());
return toggleTagAssignment(targets.stream().map(target -> target.getControllerId())
.collect(Collectors.toList()), tag.getName());
}
/**
@@ -584,8 +583,8 @@ public class TargetManagement {
@NotNull final String tagName) {
final TargetTag tag = targetTagRepository.findByNameEquals(tagName);
final List<Target> alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, targetIds);
final List<Target> allTargets = targetRepository
.findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds));
final List<Target> allTargets = targetRepository.findAll(TargetSpecifications
.byControllerIdWithStatusAndTagsInJoin(targetIds));
// all are already assigned -> unassign
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
// able to order based on
// 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),
orderByDistributionId), 1)
.when(cb.equal(targetRoot.get(Target_.assignedDistributionSet).get(DistributionSet_.id),
orderByDistributionId), 2)
.otherwise(100);
orderByDistributionId), 2).otherwise(100);
// multiselect statement order by the select case and controllerId
query.distinct(true);
// build the specifications and then to predicates necessary by the
// given filters
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
selectTargetWithNoTag, true, filterByTagNames),
targetRoot, query, cb);
selectTargetWithNoTag, true, filterByTagNames), targetRoot, query, cb);
// if we have some predicates then add it to the where clause of the
// multiselect
@@ -828,8 +826,9 @@ public class TargetManagement {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<TargetIdName> query = cb.createQuery(TargetIdName.class);
final Root<Target> targetRoot = query.from(Target.class);
return entityManager.createQuery(query.multiselect(targetRoot.get(Target_.id),
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name))).getResultList();
return entityManager.createQuery(
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(
buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId,
selectTargetWithNoTag, false, filterByTagNames),
targetRoot, multiselect, cb);
selectTargetWithNoTag, false, filterByTagNames), targetRoot, multiselect, cb);
// if we have some predicates then add it to the where clause of the
// multiselect
@@ -905,8 +903,7 @@ public class TargetManagement {
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name),
targetRoot.get(pageRequest.getSort().iterator().next().getProperty()));
final Specification<Target> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class,
entityManager);
final Specification<Target> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class);
final List<Specification<Target>> specList = new ArrayList<>();
specList.add(spec);
@@ -1003,8 +1000,7 @@ public class TargetManagement {
* to be created.
* @return the created {@link Target}s
*
* @throws {@link
* EntityAlreadyExistsException} of one of the given targets
* @throws {@link EntityAlreadyExistsException} of one of the given targets
* already exist.
*/
@Modifying
@@ -1012,8 +1008,8 @@ public class TargetManagement {
@NotNull
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
public List<Target> createTargets(@NotNull final List<Target> targets) {
if (targetRepository.countByControllerIdIn(
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList())) > 0) {
if (targetRepository.countByControllerIdIn(targets.stream().map(target -> target.getControllerId())
.collect(Collectors.toList())) > 0) {
throw new EntityAlreadyExistsException();
}
final List<Target> savedTargets = new ArrayList<>();
@@ -1045,8 +1041,8 @@ public class TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
public List<Target> createTargets(@NotNull final Collection<Target> targets,
@NotNull final TargetUpdateStatus status, final long lastTargetQuery, final URI address) {
if (targetRepository.countByControllerIdIn(
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList())) > 0) {
if (targetRepository.countByControllerIdIn(targets.stream().map(target -> target.getControllerId())
.collect(Collectors.toList())) > 0) {
throw new EntityAlreadyExistsException();
}
final List<Target> savedTargets = new ArrayList<>();
@@ -1080,8 +1076,7 @@ public class TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
public Long countTargetByTargetFilterQuery(@NotNull final TargetFilterQuery targetFilterQuery) {
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class,
entityManager);
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class);
return targetRepository.count(specs);
}
@@ -1094,7 +1089,7 @@ public class TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
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);
}

View File

@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.rsql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -19,18 +18,13 @@ import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
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.FieldValueConverter;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
@@ -104,20 +98,18 @@ public final class RSQLUtility {
* if the RSQL syntax is wrong
*/
public static <A extends Enum<A> & FieldNameProvider, T> Specification<T> parse(final String rsql,
final Class<A> fieldNameProvider, final EntityManager entityManager) {
return new RSQLSpecification<>(rsql, fieldNameProvider, entityManager);
final Class<A> fieldNameProvider) {
return new RSQLSpecification<>(rsql, fieldNameProvider);
}
private static final class RSQLSpecification<A extends Enum<A> & FieldNameProvider, T> implements Specification<T> {
private final String rsql;
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.enumType = enumType;
this.entityManager = entityManager;
}
/*
@@ -141,8 +133,7 @@ public final class RSQLUtility {
throw new RSQLParameterSyntaxException(e);
}
final JpqQueryRSQLVisitor<A, T> jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType,
entityManager);
final JpqQueryRSQLVisitor<A, T> jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType);
final List<Predicate> accept = rootNode.<List<Predicate>, String> accept(jpqQueryRSQLVisitor);
if (accept != null && !accept.isEmpty()) {
@@ -169,36 +160,14 @@ public final class RSQLUtility {
RSQLVisitor<List<Predicate>, String> {
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 CriteriaBuilder cb;
private final Class<A> enumType;
private final EntityManager entityManager;
private JpqQueryRSQLVisitor(final Root<T> root, final CriteriaBuilder cb, final Class<A> enumType,
final EntityManager entityManager) {
private JpqQueryRSQLVisitor(final Root<T> root, final CriteriaBuilder cb, final Class<A> enumType) {
this.root = root;
this.cb = cb;
this.enumType = enumType;
this.entityManager = entityManager;
}
@Override
@@ -219,134 +188,146 @@ public final class RSQLUtility {
return toSingleList(cb.conjunction());
}
private static <T> boolean isItAssociationType(final String property, final ManagedType<T> classMetadata) {
return classMetadata.getAttribute(property).isAssociation();
private List<Predicate> toSingleList(final Predicate predicate) {
return Collections.singletonList(predicate);
}
private static <T> Class<?> getPropertyType(final String property, final ManagedType<T> classMetadata) {
Class<?> propertyType;
if (classMetadata.getAttribute(property).isCollection()) {
propertyType = ((PluralAttribute) classMetadata.getAttribute(property)).getBindableJavaType();
} else {
propertyType = classMetadata.getAttribute(property).getJavaType();
private String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
String finalProperty = propertyEnum.getFieldName();
final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
validateMapParamter(propertyEnum, node, graph);
// 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,
final Metamodel metaModel) {
if (isItAssociationType(property, classMetadata)) {
final Class<?> associationType = getPropertyType(property, classMetadata);
return metaModel.managedType(associationType);
} else {
if (isItEmbeddedType(property, classMetadata)) {
final Class<?> embeddedType = getPropertyType(property, classMetadata);
return metaModel.managedType(embeddedType);
}
}
return classMetadata;
for (int i = 1; i < graph.length; i++) {
final String propertyField = graph[i];
finalProperty += FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + propertyField;
// the key of map is not in the graph
if (propertyEnum.isMap() && graph.length == (i + 1)) {
continue;
}
private static <T> boolean isItEmbeddedType(final String property, final ManagedType<T> classMetadata) {
return classMetadata.getAttribute(property).getPersistentAttributeType() == PersistentAttributeType.EMBEDDED;
if (!propertyEnum.containsSubEntityAttribute(propertyField)) {
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;
}
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;
final String[] split = finalProperty.split("\\.");
final String[] split = finalProperty.split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
if (split.length == 0) {
fieldPath = root.get(split[0]);
} else {
for (final String fieldNameSplit : split) {
// hibernate workaround because cannot get attribute of an
// PluralAttributePath, needs
// an implicit join.
// https://hibernate.atlassian.net/browse/HHH-7892
if (fieldPath == null && root.get(fieldNameSplit) != null
&& Collection.class.isAssignableFrom(root.get(fieldNameSplit).getJavaType())) {
fieldPath = root.join(fieldNameSplit);
} else {
return root.get(split[0]);
}
for (int i = 0; i < split.length; i++) {
final boolean isMapKeyField = enumField.isMap() && i == (split.length - 1);
if (isMapKeyField) {
return fieldPath;
}
final String fieldNameSplit = split[i];
fieldPath = (fieldPath != null) ? fieldPath.get(fieldNameSplit) : root.get(fieldNameSplit);
}
}
}
return fieldPath;
}
@Override
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;
try {
/**
* 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;
fieldName = getFieldEnumByName(node);
} catch (final IllegalArgumentException e) {
if (PropertyMapper.getAllowedcolmns().containsKey(classMetadata.getJavaType())) {
propertyFieldName = node.getSelector();
} else {
throw new RSQLParameterUnsupportedFieldException("The given search parameter field {"
+ node.getSelector()
+ "} does not exist, must be one of the following fields {"
+ Arrays.stream(enumType.getEnumConstants()).map(v -> v.name().toLowerCase())
.collect(Collectors.toList()) + "}", e);
}
}
final String finalProperty = validatePropertyFieldName(propertyFieldName, isDefinedInEnum, classMetadata,
metaModel, node);
final String finalProperty = getAndValidatePropertyFieldName(fieldName, node);
final List<String> values = node.getArguments();
final List<Object> transformedValue = new ArrayList<>();
final Path<Object> fieldPath = getFieldPath(finalProperty);
final Path<Object> fieldPath = getFieldPath(fieldName, finalProperty);
for (final String value : values) {
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() {
final List<String> expectedFieldList = Arrays.stream(enumType.getEnumConstants())
.map(v -> v.name().toLowerCase()).collect(Collectors.toList());
expectedFieldList.add("assignedds.name");
expectedFieldList.add("assignedds.version");
.filter(enumField -> enumField.getSubEntityAttributes().isEmpty()).map(enumField -> {
final String enumFieldName = enumField.name().toLowerCase();
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;
}
private A getFieldIdentifierByName(final ComparisonNode node) {
final String enumName = node.getSelector().toUpperCase();
private A getFieldEnumByName(final ComparisonNode node) {
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);
return Enum.valueOf(enumType, enumName);
return Enum.valueOf(enumType, enumName.toUpperCase());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -400,58 +381,86 @@ public final class RSQLUtility {
}
}
private List<Predicate> mapToPredicate(final ComparisonNode node, final Path<Object> fieldPath,
final List<String> values, final List<Object> transformedValues) {
private List<Predicate> mapToPredicate(final ComparisonNode node, Path<Object> fieldPath,
final List<String> values, final List<Object> transformedValues, final A enumField) {
// only 'equal' and 'notEqual' can handle transformed value like
// enums. The JPA API
// cannot handle object types for greaterThan etc methods.
final Object transformedValue = transformedValues.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()) {
case "=li=":
singleList = toSingleList(cb.like(cb.upper(pathOfString(fieldPath)), transformedValue.toString()
.toUpperCase()));
singleList.add(cb.like(cb.upper(pathOfString(fieldPath)), transformedValue.toString().toUpperCase()));
break;
case "==":
singleList = getEqualToPredicate(transformedValue, fieldPath);
singleList.add(getEqualToPredicate(transformedValue, fieldPath));
break;
case "!=":
singleList = toSingleList(cb.notEqual(fieldPath, transformedValue));
singleList.add(cb.notEqual(fieldPath, transformedValue));
break;
case "=gt=":
singleList = toSingleList(cb.greaterThan(pathOfString(fieldPath), value));
singleList.add(cb.greaterThan(pathOfString(fieldPath), value));
break;
case "=ge=":
singleList = toSingleList(cb.greaterThanOrEqualTo(pathOfString(fieldPath), value));
singleList.add(cb.greaterThanOrEqualTo(pathOfString(fieldPath), value));
break;
case "=lt=":
singleList = toSingleList(cb.lessThan(pathOfString(fieldPath), value));
singleList.add(cb.lessThan(pathOfString(fieldPath), value));
break;
case "=le=":
singleList = toSingleList(cb.lessThanOrEqualTo(pathOfString(fieldPath), value));
singleList.add(cb.lessThanOrEqualTo(pathOfString(fieldPath), value));
break;
case "=in=":
singleList = toSingleList(fieldPath.in(transformedValues));
singleList.add(fieldPath.in(transformedValues));
break;
case "=out=":
singleList = toSingleList(cb.not(fieldPath.in(transformedValues)));
singleList.add(cb.not(fieldPath.in(transformedValues)));
break;
default:
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) {
final String preFormattedValue = ((String) transformedValue).replace(LIKE_WILDCARD, '%');
return toSingleList(cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toString()
.toUpperCase()));
} else {
return toSingleList(cb.equal(fieldPath, transformedValue));
return cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toString().toUpperCase());
}
return cb.equal(fieldPath, transformedValue);
}
@SuppressWarnings("unchecked")
@@ -473,8 +482,5 @@ public final class RSQLUtility {
return childs;
}
private static List<Predicate> toSingleList(final Predicate p) {
return Collections.singletonList(p);
}
}
}

View File

@@ -92,8 +92,6 @@ public class DistributionSetResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
@Autowired
private EntityManager entityManager;
/**
* Handles the GET request of retrieving all {@link DistributionSet}s within
@@ -130,7 +128,7 @@ public class DistributionSetResource {
final Page<DistributionSet> findDsPage;
if (rsqlParam != null) {
findDsPage = distributionSetManagement.findDistributionSetsAll(
RSQLUtility.parse(rsqlParam, DistributionSetFields.class, entityManager), pageable, false);
RSQLUtility.parse(rsqlParam, DistributionSetFields.class), pageable, false);
} else {
findDsPage = distributionSetManagement.findDistributionSetsAll(pageable, false, null);
}
@@ -281,7 +279,7 @@ public class DistributionSetResource {
final Page<Target> targetsAssignedDS;
if (rsqlParam != null) {
targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId,
RSQLUtility.parse(rsqlParam, TargetFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
} else {
targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId, pageable);
}
@@ -331,7 +329,7 @@ public class DistributionSetResource {
final Page<Target> targetsInstalledDS;
if (rsqlParam != null) {
targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId,
RSQLUtility.parse(rsqlParam, TargetFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
} else {
targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId, pageable);
}
@@ -410,7 +408,7 @@ public class DistributionSetResource {
if (rsqlParam != null) {
metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
RSQLUtility.parse(rsqlParam, DistributionSetMetadataFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, DistributionSetMetadataFields.class), pageable);
} else {
metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
pageable);

View File

@@ -60,8 +60,6 @@ public class DistributionSetTagResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
@Autowired
private EntityManager entityManager;
/**
* Handles the GET request of retrieving all DistributionSet tags.
@@ -103,7 +101,7 @@ public class DistributionSetTagResource {
} else {
final Page<DistributionSetTag> findTargetPage = tagManagement.findAllDistributionSetTags(
RSQLUtility.parse(rsqlParam, TagFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, TagFields.class), pageable);
countTargetsAll = findTargetPage.getTotalElements();
findTargetsAll = findTargetPage;

View File

@@ -62,9 +62,6 @@ public class DistributionSetTypeResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
@Autowired
private EntityManager entityManager;
/**
* Handles the GET request of retrieving all {@link DistributionSetType}s
* within SP.
@@ -105,7 +102,7 @@ public class DistributionSetTypeResource {
Long countModulesAll;
if (rsqlParam != null) {
findModuleTypessAll = distributionSetManagement.findDistributionSetTypesByPredicate(
RSQLUtility.parse(rsqlParam, DistributionSetTypeFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, DistributionSetTypeFields.class), pageable);
countModulesAll = ((Page<DistributionSetType>) findModuleTypessAll).getTotalElements();
} else {
findModuleTypessAll = distributionSetManagement.findDistributionSetTypesAll(pageable);

View File

@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.rest.resource;
import java.io.IOException;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -75,9 +74,6 @@ public class SoftwareModuleResource {
@Autowired
private SoftwareManagement softwareManagement;
@Autowired
private EntityManager entityManager;
/**
* Handles POST request for artifact upload.
*
@@ -266,7 +262,7 @@ public class SoftwareModuleResource {
Long countModulesAll;
if (rsqlParam != null) {
findModulesAll = softwareManagement.findSoftwareModulesByPredicate(
RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class), pageable);
countModulesAll = ((Page<SoftwareModule>) findModulesAll).getTotalElements();
} else {
findModulesAll = softwareManagement.findSoftwareModulesAll(pageable);
@@ -307,8 +303,8 @@ public class SoftwareModuleResource {
* failure the JsonResponseExceptionHandler is handling the
* response.
*/
@RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
@RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }, produces = {
"application/hal+json", MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<SoftwareModulesRest> createSoftwareModules(
@RequestBody final List<SoftwareModuleRequestBodyPost> softwareModules) {
LOG.debug("creating {} softwareModules", softwareModules.size());
@@ -387,7 +383,8 @@ public class SoftwareModuleResource {
*/
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata", produces = {
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_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
@RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
@@ -405,15 +402,13 @@ public class SoftwareModuleResource {
if (rsqlParam != null) {
metaDataPage = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(softwareModuleId,
RSQLUtility.parse(rsqlParam, SoftwareModuleMetadataFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, SoftwareModuleMetadataFields.class), pageable);
} else {
metaDataPage = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(softwareModuleId, pageable);
}
return new ResponseEntity<>(
new MetadataRestPageList(SoftwareModuleMapper.toResponseSwMetadata(metaDataPage.getContent()),
metaDataPage.getTotalElements()),
HttpStatus.OK);
return new ResponseEntity<>(new MetadataRestPageList(SoftwareModuleMapper.toResponseSwMetadata(metaDataPage
.getContent()), 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
* data
*/
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = {
MediaType.APPLICATION_JSON_VALUE })
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<MetadataRest> getMetadataValue(@PathVariable final Long softwareModuleId,
@PathVariable final String metadataKey) {
// check if distribution set exists otherwise throw exception
@@ -487,8 +481,8 @@ public class SoftwareModuleResource {
* the created meta data
*/
@RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/metadata", consumes = {
MediaType.APPLICATION_JSON_VALUE,
"application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
MediaType.APPLICATION_JSON_VALUE, "application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE,
"application/hal+json" })
public ResponseEntity<List<MetadataRest>> createMetadata(@PathVariable final Long softwareModuleId,
@RequestBody final List<MetadataRest> metadataRest) {
// check if software module exists otherwise throw exception immediately
@@ -501,8 +495,7 @@ public class SoftwareModuleResource {
}
private SoftwareModule findSoftwareModuleWithExceptionIfNotFound(final Long softwareModuleId,
final Long artifactId) {
private SoftwareModule findSoftwareModuleWithExceptionIfNotFound(final Long softwareModuleId, final Long artifactId) {
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
if (module == null) {
throw new EntityNotFoundException("SoftwareModule with Id {" + softwareModuleId + "} does not exist");

View File

@@ -94,7 +94,7 @@ public class SoftwareModuleTypeResource {
Long countModulesAll;
if (rsqlParam != null) {
findModuleTypessAll = softwareManagement.findSoftwareModuleTypesByPredicate(
RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class), pageable);
countModulesAll = ((Page<SoftwareModuleType>) findModuleTypessAll).getTotalElements();
} else {
findModuleTypessAll = softwareManagement.findSoftwareModuleTypesAll(pageable);

View File

@@ -135,7 +135,7 @@ public class TargetResource {
final Long countTargetsAll;
if (rsqlParam != null) {
final Page<Target> findTargetPage = targetManagement.findTargetsAll(
RSQLUtility.parse(rsqlParam, TargetFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
countTargetsAll = findTargetPage.getTotalElements();
findTargetsAll = findTargetPage;
} else {
@@ -284,7 +284,7 @@ public class TargetResource {
final Slice<Action> activeActions;
final Long totalActionCount;
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);
totalActionCount = deploymentManagement.countActionsByTarget(parse, foundTarget);
} else {

View File

@@ -103,7 +103,7 @@ public class TargetTagResource {
} else {
final Page<TargetTag> findTargetPage = tagManagement.findAllTargetTags(
RSQLUtility.parse(rsqlParam, TagFields.class, entityManager), pageable);
RSQLUtility.parse(rsqlParam, TagFields.class), pageable);
countTargetsAll = findTargetPage.getTotalElements();
findTargetsAll = findTargetPage;

View File

@@ -12,14 +12,12 @@ import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
@@ -27,11 +25,11 @@ import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
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.SoftwareModuleFields;
import org.eclipse.hawkbit.repository.TargetFields;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.rsql.RSQLParameterSyntaxException;
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.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@@ -60,33 +56,87 @@ public class RSQLUtilityTest {
private CriteriaQuery<SoftwareModule> criteriaQueryMock;
@Mock
private CriteriaBuilder criteriaBuilderMock;
@Mock
private EntityManager entityManager;
@Mock
private Metamodel metamodel;
@Mock
private ManagedType managedType;
@Mock
private Attribute attribute;
@Test(expected = RSQLParameterSyntaxException.class)
@Test
public void wrongRsqlSyntaxThrowSyntaxException() {
final String wrongRSQL = "name==abc;d";
when(entityManager.getMetamodel()).thenReturn(metamodel);
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
try {
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
fail();
} catch (final RSQLParameterSyntaxException e) {
}
}
@Test(expected = RSQLParameterUnsupportedFieldException.class)
@Test
public void wrongFieldThrowUnsupportedFieldException() {
final String wrongRSQL = "unknownField==abc";
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
doEntitySetup(SoftwareModule.class);
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
try {
RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
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
@@ -100,11 +150,9 @@ public class RSQLUtilityTest {
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
mock(Predicate.class));
doEntitySetup(SoftwareModule.class);
// test
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
// verfication
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.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
mock(Predicate.class));
doEntitySetup(SoftwareModule.class);
// test
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
// verfication
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.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class))).thenReturn(
mock(Predicate.class));
doEntitySetup(SoftwareModule.class);
// test
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
// verfication
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
@@ -159,10 +205,9 @@ public class RSQLUtilityTest {
mock(Predicate.class));
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock)))).thenReturn(
pathOfString(baseSoftwareModuleRootMock));
doEntitySetup(SoftwareModule.class);
// test
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, entityManager).toPredicate(
baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
// verfication
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
@@ -178,10 +223,9 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
doEntitySetup(TestValueEnum.class);
// test
RSQLUtility.parse(correctRsql, TestFieldEnum.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
RSQLUtility.parse(correctRsql, TestFieldEnum.class).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock,
criteriaBuilderMock);
// verfication
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
@@ -196,11 +240,9 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) TestValueEnum.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
doEntitySetup(TestValueEnum.class);
try {
// test
RSQLUtility.parse(correctRsql, TestFieldEnum.class, entityManager).toPredicate(baseSoftwareModuleRootMock,
RSQLUtility.parse(correctRsql, TestFieldEnum.class).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
fail("missing RSQLParameterUnsupportedFieldException for wrong enum value");
} 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")
private <Y> Path<Y> pathOfString(final Path<?> path) {
return (Path<Y>) path;