Ensure a '.' character is allowed to be used in target filter query for metadata key and attribute name (#1186)
* Adapted code to allow '.' inside of metadata key and attribute names Signed-off-by: Markus Block <markus.block@bosch-si.com> * added handling of corner cases Signed-off-by: Markus Block <markus.block@bosch-si.com> * Adapted metadata and attribute tests to check that dot is allowed Signed-off-by: Markus Block <markus.block@bosch-si.com> * fixed documentation Signed-off-by: Markus Block <markus.block@bosch-si.com> * Allow usage of dot in key names for every map attribute, e.g. also for metadata in distribution set Signed-off-by: Markus Block <markus.block@bosch-si.com> * fixed typo Signed-off-by: Markus Block <markus.block@bosch-si.com> * adapted test key to ensure a dot can be used Signed-off-by: Markus Block <markus.block@bosch-si.com> * fixed typo Signed-off-by: Markus Block <markus.block@bosch-si.com>
This commit is contained in:
@@ -128,7 +128,8 @@ Custom target filter overview and filter management.
|
|||||||
The basic syntax to filter is: `field<basic_operator>value <composite_operator> field<basic_operator>value <...>`
|
The basic syntax to filter is: `field<basic_operator>value <composite_operator> field<basic_operator>value <...>`
|
||||||
|
|
||||||
- `field`: is the name of the resource field.
|
- `field`: is the name of the resource field.
|
||||||
- `value`: is the value of the target field
|
- `value`: is the expected value of the target field.
|
||||||
|
- Use `*` for wildcard matches.
|
||||||
- `<basic_operator>`: Are operators to do simple queries. Supported basic operators are:
|
- `<basic_operator>`: Are operators to do simple queries. Supported basic operators are:
|
||||||
- `==` : equal
|
- `==` : equal
|
||||||
- `!=` : not equal
|
- `!=` : not equal
|
||||||
@@ -136,8 +137,6 @@ The basic syntax to filter is: `field<basic_operator>value <composite_operator>
|
|||||||
- `<composite_operator>`: Are operators to join simple queries: Supported composite operators are:
|
- `<composite_operator>`: Are operators to join simple queries: Supported composite operators are:
|
||||||
- `and`
|
- `and`
|
||||||
- `or`
|
- `or`
|
||||||
- Use `=IN=` for 'in' parameter.(Example: name=IN=(target1,target2).
|
|
||||||
- Use `*` for wildcard matches.
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -25,7 +27,7 @@ public interface FieldNameProvider {
|
|||||||
/**
|
/**
|
||||||
* Separator for the sub attributes
|
* Separator for the sub attributes
|
||||||
*/
|
*/
|
||||||
String SUB_ATTRIBUTE_SEPERATOR = ".";
|
String SUB_ATTRIBUTE_SEPARATOR = ".";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the string representation of the underlying persistence field
|
* @return the string representation of the underlying persistence field
|
||||||
@@ -33,6 +35,26 @@ public interface FieldNameProvider {
|
|||||||
*/
|
*/
|
||||||
String getFieldName();
|
String getFieldName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sub attributes
|
||||||
|
*
|
||||||
|
* @param propertyFieldName
|
||||||
|
* the given field
|
||||||
|
* @return array consisting of sub attributes
|
||||||
|
*/
|
||||||
|
default String[] getSubAttributes(final String propertyFieldName) {
|
||||||
|
if (isMap()) {
|
||||||
|
final String[] subAttributes = propertyFieldName.split("\\" + SUB_ATTRIBUTE_SEPARATOR, 2);
|
||||||
|
// [0] fieldname |[1] keyname
|
||||||
|
final String mapKeyName = subAttributes.length == 2 ? subAttributes[1] : null;
|
||||||
|
if (StringUtils.isEmpty(mapKeyName)) {
|
||||||
|
return new String[] { getFieldName() };
|
||||||
|
}
|
||||||
|
return new String[] { getFieldName(), mapKeyName };
|
||||||
|
}
|
||||||
|
return propertyFieldName.split("\\" + SUB_ATTRIBUTE_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the sub entity the given field.
|
* Contains the sub entity the given field.
|
||||||
*
|
*
|
||||||
@@ -47,7 +69,7 @@ public interface FieldNameProvider {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (final String attribute : subEntityAttributes) {
|
for (final String attribute : subEntityAttributes) {
|
||||||
final String[] graph = attribute.split("\\" + SUB_ATTRIBUTE_SEPERATOR);
|
final String[] graph = attribute.split("\\" + SUB_ATTRIBUTE_SEPARATOR);
|
||||||
|
|
||||||
for (final String subAttribute : graph) {
|
for (final String subAttribute : graph) {
|
||||||
if (subAttribute.equalsIgnoreCase(propertyField)) {
|
if (subAttribute.equalsIgnoreCase(propertyField)) {
|
||||||
@@ -74,7 +96,7 @@ public interface FieldNameProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the entity field a {@link Map}.
|
* Is the entity field a {@link Map} consisting of key-value pairs.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> is a map <code>false</code> is not a map
|
* @return <code>true</code> is a map <code>false</code> is not a map
|
||||||
*/
|
*/
|
||||||
@@ -84,7 +106,7 @@ public interface FieldNameProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the field, that identifies the entity.
|
* Returns the name of the field, that identifies the entity.
|
||||||
*
|
*
|
||||||
* @return the name of the identifier, by default 'id'
|
* @return the name of the identifier, by default 'id'
|
||||||
*/
|
*/
|
||||||
default String identifierFieldName() {
|
default String identifierFieldName() {
|
||||||
|
|||||||
@@ -135,4 +135,4 @@ public enum TargetFields implements FieldNameProvider {
|
|||||||
public String getFieldName() {
|
public String getFieldName() {
|
||||||
return fieldName;
|
return fieldName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,15 +8,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||||
|
|
||||||
import cz.jirutka.rsql.parser.ast.ComparisonNode;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import cz.jirutka.rsql.parser.ast.ComparisonNode;
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldNameProvider> {
|
public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldNameProvider> {
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
|||||||
|
|
||||||
protected A getFieldEnumByName(final ComparisonNode node) {
|
protected A getFieldEnumByName(final ComparisonNode node) {
|
||||||
String enumName = node.getSelector();
|
String enumName = node.getSelector();
|
||||||
final String[] graph = getSubAttributesFrom(enumName);
|
final String[] graph = enumName.split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR);
|
||||||
if (graph.length != 0) {
|
if (graph.length != 0) {
|
||||||
enumName = graph[0];
|
enumName = graph[0];
|
||||||
}
|
}
|
||||||
@@ -42,13 +43,9 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String[] getSubAttributesFrom(final String property) {
|
|
||||||
return property.split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
|
protected String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
|
||||||
|
|
||||||
final String[] graph = getSubAttributesFrom(node.getSelector());
|
final String[] graph = propertyEnum.getSubAttributes(node.getSelector());
|
||||||
|
|
||||||
validateMapParameter(propertyEnum, node, graph);
|
validateMapParameter(propertyEnum, node, graph);
|
||||||
|
|
||||||
@@ -62,7 +59,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
|||||||
for (int i = 1; i < graph.length; i++) {
|
for (int i = 1; i < graph.length; i++) {
|
||||||
|
|
||||||
final String propertyField = graph[i];
|
final String propertyField = graph[i];
|
||||||
fieldNameBuilder.append(FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR).append(propertyField);
|
fieldNameBuilder.append(FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR).append(propertyField);
|
||||||
|
|
||||||
// the key of map is not in the graph
|
// the key of map is not in the graph
|
||||||
if (propertyEnum.isMap() && graph.length == (i + 1)) {
|
if (propertyEnum.isMap() && graph.length == (i + 1)) {
|
||||||
@@ -126,7 +123,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
|||||||
final String enumFieldName = enumField.name().toLowerCase();
|
final String enumFieldName = enumField.name().toLowerCase();
|
||||||
|
|
||||||
if (enumField.isMap()) {
|
if (enumField.isMap()) {
|
||||||
return enumFieldName + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + "keyName";
|
return enumFieldName + FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR + "keyName";
|
||||||
}
|
}
|
||||||
|
|
||||||
return enumFieldName;
|
return enumFieldName;
|
||||||
@@ -136,7 +133,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
|||||||
.filter(enumField -> !enumField.getSubEntityAttributes().isEmpty()).flatMap(enumField -> {
|
.filter(enumField -> !enumField.getSubEntityAttributes().isEmpty()).flatMap(enumField -> {
|
||||||
final List<String> subEntity = enumField
|
final List<String> subEntity = enumField
|
||||||
.getSubEntityAttributes().stream().map(fieldName -> enumField.name().toLowerCase()
|
.getSubEntityAttributes().stream().map(fieldName -> enumField.name().toLowerCase()
|
||||||
+ FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + fieldName)
|
+ FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR + fieldName)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
return subEntity.stream();
|
return subEntity.stream();
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -179,7 +179,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Path<Object> getFieldPath(final A enumField, final String finalProperty) {
|
private Path<Object> getFieldPath(final A enumField, final String finalProperty) {
|
||||||
return (Path<Object>) getFieldPath(root, getSubAttributesFrom(finalProperty), enumField.isMap(),
|
return (Path<Object>) getFieldPath(root, enumField.getSubAttributes(finalProperty), enumField.isMap(),
|
||||||
this::getJoinFieldPath).orElseThrow(
|
this::getJoinFieldPath).orElseThrow(
|
||||||
() -> createRSQLParameterUnsupportedException("RSQL field path cannot be empty", null));
|
() -> createRSQLParameterUnsupportedException("RSQL field path cannot be empty", null));
|
||||||
}
|
}
|
||||||
@@ -377,7 +377,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
|||||||
private Predicate getOutPredicate(final List<Object> transformedValues, final String finalProperty,
|
private Predicate getOutPredicate(final List<Object> transformedValues, final String finalProperty,
|
||||||
final A enumField, final Path<Object> fieldPath) {
|
final A enumField, final Path<Object> fieldPath) {
|
||||||
|
|
||||||
final String[] fieldNames = getSubAttributesFrom(finalProperty);
|
final String[] fieldNames = enumField.getSubAttributes(finalProperty);
|
||||||
final List<String> outParams = transformedValues.stream().filter(String.class::isInstance)
|
final List<String> outParams = transformedValues.stream().filter(String.class::isInstance)
|
||||||
.map(String.class::cast).map(String::toUpperCase).collect(Collectors.toList());
|
.map(String.class::cast).map(String::toUpperCase).collect(Collectors.toList());
|
||||||
|
|
||||||
@@ -423,7 +423,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String[] graph = getSubAttributesFrom(node.getSelector());
|
final String[] graph = enumField.getSubAttributes(node.getSelector());
|
||||||
|
|
||||||
final String keyValue = graph[graph.length - 1];
|
final String keyValue = graph[graph.length - 1];
|
||||||
if (fieldPath instanceof MapJoin) {
|
if (fieldPath instanceof MapJoin) {
|
||||||
@@ -469,7 +469,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String sqlValue = toSQL((String) transformedValue);
|
final String sqlValue = toSQL((String) transformedValue);
|
||||||
final String[] fieldNames = getSubAttributesFrom(finalProperty);
|
final String[] fieldNames = enumField.getSubAttributes(finalProperty);
|
||||||
|
|
||||||
if (isSimpleField(fieldNames, enumField.isMap())) {
|
if (isSimpleField(fieldNames, enumField.isMap())) {
|
||||||
return toNullOrNotLikePredicate(fieldPath, sqlValue);
|
return toNullOrNotLikePredicate(fieldPath, sqlValue);
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||||
@@ -47,13 +49,13 @@ public class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
ds2 = distributionSetManagement.update(entityFactory.distributionSet().update(ds2.getId()).description("DS%"));
|
ds2 = distributionSetManagement.update(entityFactory.distributionSet().update(ds2.getId()).description("DS%"));
|
||||||
createDistributionSetMetadata(ds2.getId(), entityFactory.generateDsMetadata("metaKey", "value"));
|
createDistributionSetMetadata(ds2.getId(), entityFactory.generateDsMetadata("metaKey", "value"));
|
||||||
|
|
||||||
final DistributionSetTag targetTag = distributionSetTagManagement
|
final DistributionSetTag distSetTag = distributionSetTagManagement
|
||||||
.create(entityFactory.tag().create().name("Tag1"));
|
.create(entityFactory.tag().create().name("Tag1"));
|
||||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag2"));
|
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag2"));
|
||||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag3"));
|
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag3"));
|
||||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag4"));
|
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag4"));
|
||||||
|
|
||||||
distributionSetManagement.assignTag(Arrays.asList(ds.getId(), ds2.getId()), targetTag.getId());
|
distributionSetManagement.assignTag(Arrays.asList(ds.getId(), ds2.getId()), distSetTag.getId());
|
||||||
|
|
||||||
distributionSetManagement
|
distributionSetManagement
|
||||||
.create(entityFactory.distributionSet().create().name("test123").version("noDescription"));
|
.create(entityFactory.distributionSet().create().name("test123").version("noDescription"));
|
||||||
@@ -151,12 +153,27 @@ public class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Test filter distribution set by metadata")
|
@Description("Test filter distribution set by metadata")
|
||||||
public void testFilterByMetadata() {
|
public void testFilterByMetadata() {
|
||||||
|
createDistributionSetWithMetadata("key.dot", "value.dot");
|
||||||
|
|
||||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
||||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==*v*", 2);
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==*v*", 2);
|
||||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
||||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=in=(metaValue,notexist)", 1);
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=in=(metaValue,notexist)", 1);
|
||||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=out=(metaValue,notexist)", 1);
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=out=(metaValue,notexist)", 1);
|
||||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".notExist==metaValue", 0);
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".notExist==metaValue", 0);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.dot==value.dot", 1);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.dot*==value.dot", 0);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.*==value.dot", 0);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.==value.dot", 0);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key*==value.dot", 0);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".*==value.dot", 0);
|
||||||
|
assertRSQLQuery(DistributionSetFields.METADATA.name() + "..==value.dot", 0);
|
||||||
|
assertRSQLQueryThrowsException(DistributionSetFields.METADATA.name() + ".==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
assertRSQLQueryThrowsException(DistributionSetFields.METADATA.name() + "*==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
assertRSQLQueryThrowsException(DistributionSetFields.METADATA.name() + "==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,4 +183,19 @@ public class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(find).as("Founded entity is should not be null").isNotNull();
|
assertThat(find).as("Founded entity is should not be null").isNotNull();
|
||||||
assertThat(countAll).as("Founded entity size is wrong").isEqualTo(excpectedEntity);
|
assertThat(countAll).as("Founded entity size is wrong").isEqualTo(excpectedEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T extends Throwable> void assertRSQLQueryThrowsException(final String rsqlParam,
|
||||||
|
final Class<T> expectedException) {
|
||||||
|
assertThatExceptionOfType(expectedException)
|
||||||
|
.isThrownBy(() -> RSQLUtility.validateRsqlFor(rsqlParam, DistributionSetFields.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DistributionSet createDistributionSetWithMetadata(final String metadataKeyName,
|
||||||
|
final String metadataValue) {
|
||||||
|
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||||
|
createDistributionSetMetadata(distributionSet.getId(),
|
||||||
|
entityFactory.generateDsMetadata(metadataKeyName, metadataValue));
|
||||||
|
return distributionSet;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.assertj.core.util.Maps;
|
||||||
import org.eclipse.hawkbit.repository.TargetFields;
|
import org.eclipse.hawkbit.repository.TargetFields;
|
||||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
@@ -148,12 +149,27 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Test filter target by attribute")
|
@Description("Test filter target by attribute")
|
||||||
public void testFilterByAttribute() {
|
public void testFilterByAttribute() {
|
||||||
|
createTargetWithAttributes("test.dot", "value.dot");
|
||||||
|
|
||||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==1.1", 1);
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==1.1", 1);
|
||||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision!=1.1", 1);
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision!=1.1", 1);
|
||||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==1*", 2);
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==1*", 2);
|
||||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==noExist*", 0);
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==noExist*", 0);
|
||||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision=in=(1.1,notexist)", 1);
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision=in=(1.1,notexist)", 1);
|
||||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision=out=(1.1)", 1);
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision=out=(1.1)", 1);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".test.dot==value.dot", 1);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".key.dot*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".key.*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".key.==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".key*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + "..==value.dot", 0);
|
||||||
|
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + ".==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + "*==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + "==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -214,6 +230,8 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Test filter target by metadata")
|
@Description("Test filter target by metadata")
|
||||||
public void testFilterByMetadata() {
|
public void testFilterByMetadata() {
|
||||||
|
createTargetWithMetadata("key.dot", "value.dot");
|
||||||
|
|
||||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
||||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==*v*", 2);
|
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==*v*", 2);
|
||||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
||||||
@@ -223,6 +241,19 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey!=metaValue", 1);
|
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey!=metaValue", 1);
|
||||||
assertRSQLQuery(TargetFields.METADATA.name() + ".notExist!=metaValue", 0);
|
assertRSQLQuery(TargetFields.METADATA.name() + ".notExist!=metaValue", 0);
|
||||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey!=notExist", 2);
|
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey!=notExist", 2);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + ".key.dot==value.dot", 1);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + ".key.dot*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + ".key.*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + ".key.==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + ".key*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + ".*==value.dot", 0);
|
||||||
|
assertRSQLQuery(TargetFields.METADATA.name() + "..==value.dot", 0);
|
||||||
|
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + ".==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + "*==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
|
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + "==value.dot",
|
||||||
|
RSQLParameterUnsupportedFieldException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -259,6 +290,10 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
final String rsql5 = "wrongfield == abcd";
|
final String rsql5 = "wrongfield == abcd";
|
||||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||||
.isThrownBy(() -> RSQLUtility.validateRsqlFor(rsql5, TargetFields.class));
|
.isThrownBy(() -> RSQLUtility.validateRsqlFor(rsql5, TargetFields.class));
|
||||||
|
|
||||||
|
final String rsql6 = "ATTRIBUTE.test.dot == test and ATTRIBUTE.subkey2 == test"
|
||||||
|
+ " and METADATA.test.dot == abcd and METADATA.metavalue2 == asdfg";
|
||||||
|
RSQLUtility.validateRsqlFor(rsql6, TargetFields.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertRSQLQuery(final String rsqlParam, final long expcetedTargets) {
|
private void assertRSQLQuery(final String rsqlParam, final long expcetedTargets) {
|
||||||
@@ -267,4 +302,24 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(findTargetPage).isNotNull();
|
assertThat(findTargetPage).isNotNull();
|
||||||
assertThat(countTargetsAll).isEqualTo(expcetedTargets);
|
assertThat(countTargetsAll).isEqualTo(expcetedTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T extends Throwable> void assertRSQLQueryThrowsException(final String rsqlParam,
|
||||||
|
final Class<T> expectedException) {
|
||||||
|
assertThatExceptionOfType(expectedException)
|
||||||
|
.isThrownBy(() -> RSQLUtility.validateRsqlFor(rsqlParam, TargetFields.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Target createTargetWithMetadata(final String metadataKeyName, final String metadataValue) {
|
||||||
|
final Target target = testdataFactory.createTarget();
|
||||||
|
createTargetMetadata(target.getControllerId(),
|
||||||
|
entityFactory.generateTargetMetadata(metadataKeyName, metadataValue));
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Target createTargetWithAttributes(final String attributeName, final String attributeValue) {
|
||||||
|
final Target target = testdataFactory.createTarget();
|
||||||
|
controllerManagement.updateControllerAttributes(target.getControllerId(),
|
||||||
|
Maps.newHashMap(attributeName, attributeValue), null);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1025,7 +1025,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
|||||||
public void createMetadata() throws Exception {
|
public void createMetadata() throws Exception {
|
||||||
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
final DistributionSet testDS = testdataFactory.createDistributionSet("one");
|
||||||
|
|
||||||
final String knownKey1 = "knownKey1";
|
final String knownKey1 = "known.key.1.1";
|
||||||
final String knownKey2 = "knownKey2";
|
final String knownKey2 = "knownKey2";
|
||||||
|
|
||||||
final String knownValue1 = "knownValue1";
|
final String knownValue1 = "knownValue1";
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
package org.eclipse.hawkbit.mgmt.rest.resource;
|
package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.not;
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
@@ -1611,8 +1611,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
|||||||
// create target with attributes
|
// create target with attributes
|
||||||
final String knownTargetId = "targetIdNeedsUpdate";
|
final String knownTargetId = "targetIdNeedsUpdate";
|
||||||
final Map<String, String> knownControllerAttrs = new HashMap<>();
|
final Map<String, String> knownControllerAttrs = new HashMap<>();
|
||||||
knownControllerAttrs.put("a", "1");
|
knownControllerAttrs.put("a.1", "1");
|
||||||
knownControllerAttrs.put("b", "2");
|
knownControllerAttrs.put("b.2", "2");
|
||||||
testdataFactory.createTarget(knownTargetId);
|
testdataFactory.createTarget(knownTargetId);
|
||||||
controllerManagement.updateControllerAttributes(knownTargetId, knownControllerAttrs, null);
|
controllerManagement.updateControllerAttributes(knownTargetId, knownControllerAttrs, null);
|
||||||
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isFalse();
|
assertThat(targetManagement.isControllerAttributesRequested(knownTargetId)).isFalse();
|
||||||
@@ -1721,7 +1721,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
|||||||
final String knownControllerId = "targetIdWithMetadata";
|
final String knownControllerId = "targetIdWithMetadata";
|
||||||
testdataFactory.createTarget(knownControllerId);
|
testdataFactory.createTarget(knownControllerId);
|
||||||
|
|
||||||
final String knownKey1 = "knownKey1";
|
final String knownKey1 = "known.key.1";
|
||||||
final String knownKey2 = "knownKey2";
|
final String knownKey2 = "knownKey2";
|
||||||
|
|
||||||
final String knownValue1 = "knownValue1";
|
final String knownValue1 = "knownValue1";
|
||||||
|
|||||||
Reference in New Issue
Block a user