Refactor RSQL serach fields related classes (#1834)
Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
* Sort and search fields for actions.
|
||||
*/
|
||||
@Getter
|
||||
public enum ActionFields implements FieldNameProvider, FieldValueConverter<ActionFields> {
|
||||
public enum ActionFields implements RsqlQueryField, FieldValueConverter<ActionFields> {
|
||||
|
||||
ID("id"),
|
||||
STATUS("active"),
|
||||
@@ -26,29 +26,29 @@ public enum ActionFields implements FieldNameProvider, FieldValueConverter<Actio
|
||||
LASTSTATUSCODE("lastActionStatusCode"),
|
||||
WEIGHT("weight"),
|
||||
TARGET("target",
|
||||
TargetFields.ID.getFieldName(), TargetFields.NAME.getFieldName(),
|
||||
TargetFields.UPDATESTATUS.getFieldName(), TargetFields.IPADDRESS.getFieldName()),
|
||||
TargetFields.ID.getJpaEntityFieldName(), TargetFields.NAME.getJpaEntityFieldName(),
|
||||
TargetFields.UPDATESTATUS.getJpaEntityFieldName(), TargetFields.IPADDRESS.getJpaEntityFieldName()),
|
||||
DISTRIBUTIONSET("distributionSet",
|
||||
DistributionSetFields.ID.getFieldName(),
|
||||
DistributionSetFields.NAME.getFieldName(), DistributionSetFields.VERSION.getFieldName(),
|
||||
DistributionSetFields.TYPE.getFieldName()),
|
||||
ROLLOUT("rollout", RolloutFields.ID.getFieldName(), RolloutFields.NAME.getFieldName()),
|
||||
ROLLOUTGROUP("rolloutGroup", RolloutGroupFields.ID.getFieldName(), RolloutGroupFields.NAME.getFieldName()),
|
||||
DistributionSetFields.ID.getJpaEntityFieldName(),
|
||||
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName(),
|
||||
DistributionSetFields.TYPE.getJpaEntityFieldName()),
|
||||
ROLLOUT("rollout", RolloutFields.ID.getJpaEntityFieldName(), RolloutFields.NAME.getJpaEntityFieldName()),
|
||||
ROLLOUTGROUP("rolloutGroup", RolloutGroupFields.ID.getJpaEntityFieldName(), RolloutGroupFields.NAME.getJpaEntityFieldName()),
|
||||
EXTERNALREF("externalRef");
|
||||
|
||||
private static final String ACTIVE = "pending";
|
||||
private static final String INACTIVE = "finished";
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private final List<String> subEntityAttributes;
|
||||
|
||||
ActionFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
ActionFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = Collections.emptyList();
|
||||
}
|
||||
|
||||
ActionFields(final String fieldName, final String... subEntityAttributes) {
|
||||
this.fieldName = fieldName;
|
||||
ActionFields(final String jpaEntityFieldName, final String... subEntityAttributes) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = List.of(subEntityAttributes);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ import lombok.Getter;
|
||||
* Sort and search fields for action status.
|
||||
*/
|
||||
@Getter
|
||||
public enum ActionStatusFields implements FieldNameProvider {
|
||||
public enum ActionStatusFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
REPORTEDAT("createdAt");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
ActionStatusFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
ActionStatusFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import java.util.Optional;
|
||||
* REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum DistributionSetFields implements FieldNameProvider {
|
||||
public enum DistributionSetFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
TYPE("type.key"),
|
||||
@@ -32,29 +32,29 @@ public enum DistributionSetFields implements FieldNameProvider {
|
||||
LASTMODIFIEDAT("lastModifiedAt"),
|
||||
VERSION("version"),
|
||||
COMPLETE("complete"),
|
||||
MODULE("modules", SoftwareModuleFields.ID.getFieldName(), SoftwareModuleFields.NAME.getFieldName()),
|
||||
MODULE("modules", SoftwareModuleFields.ID.getJpaEntityFieldName(), SoftwareModuleFields.NAME.getJpaEntityFieldName()),
|
||||
TAG("tags.name"),
|
||||
METADATA("metadata", new SimpleImmutableEntry<>("key", "value")),
|
||||
VALID("valid");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private final Entry<String, String> subEntityMapTuple;
|
||||
private final List<String> subEntityAttributes;
|
||||
|
||||
DistributionSetFields(final String fieldName) {
|
||||
this(fieldName, null, Collections.emptyList());
|
||||
DistributionSetFields(final String jpaEntityFieldName) {
|
||||
this(jpaEntityFieldName, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
DistributionSetFields(final String fieldName, final String... subEntityAttributes) {
|
||||
this(fieldName, null, List.of(subEntityAttributes));
|
||||
DistributionSetFields(final String jpaEntityFieldName, final String... subEntityAttributes) {
|
||||
this(jpaEntityFieldName, null, List.of(subEntityAttributes));
|
||||
}
|
||||
|
||||
DistributionSetFields(final String fieldName, final Entry<String, String> subEntityMapTuple) {
|
||||
this(fieldName, subEntityMapTuple, Collections.emptyList());
|
||||
DistributionSetFields(final String jpaEntityFieldName, final Entry<String, String> subEntityMapTuple) {
|
||||
this(jpaEntityFieldName, subEntityMapTuple, Collections.emptyList());
|
||||
}
|
||||
|
||||
DistributionSetFields(final String fieldName, final Entry<String, String> subEntityMapTuple, List<String> subEntityAttributes) {
|
||||
this.fieldName = fieldName;
|
||||
DistributionSetFields(final String jpaEntityFieldName, final Entry<String, String> subEntityMapTuple, List<String> subEntityAttributes) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityMapTuple = subEntityMapTuple;
|
||||
this.subEntityAttributes = subEntityAttributes;
|
||||
}
|
||||
|
||||
@@ -15,19 +15,19 @@ import lombok.Getter;
|
||||
* Sort fields for DistributionSetMetadata.
|
||||
*/
|
||||
@Getter
|
||||
public enum DistributionSetMetadataFields implements FieldNameProvider {
|
||||
public enum DistributionSetMetadataFields implements RsqlQueryField {
|
||||
|
||||
KEY("key"),
|
||||
VALUE("value");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
DistributionSetMetadataFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
DistributionSetMetadataFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifierFieldName() {
|
||||
return KEY.getFieldName();
|
||||
return KEY.getJpaEntityFieldName();
|
||||
}
|
||||
}
|
||||
@@ -21,25 +21,25 @@ import java.util.List;
|
||||
* filtering over distribution set fields also.
|
||||
*/
|
||||
@Getter
|
||||
public enum DistributionSetTagFields implements FieldNameProvider {
|
||||
public enum DistributionSetTagFields implements RsqlQueryField {
|
||||
|
||||
ID(TagFields.ID.getFieldName()),
|
||||
NAME(TagFields.NAME.getFieldName()),
|
||||
DESCRIPTION(TagFields.DESCRIPTION.getFieldName()),
|
||||
COLOUR(TagFields.COLOUR.getFieldName()),
|
||||
ID(TagFields.ID.getJpaEntityFieldName()),
|
||||
NAME(TagFields.NAME.getJpaEntityFieldName()),
|
||||
DESCRIPTION(TagFields.DESCRIPTION.getJpaEntityFieldName()),
|
||||
COLOUR(TagFields.COLOUR.getJpaEntityFieldName()),
|
||||
DISTRIBUTIONSET("assignedToDistributionSet",
|
||||
DistributionSetFields.ID.getFieldName(), DistributionSetFields.NAME.getFieldName());
|
||||
DistributionSetFields.ID.getJpaEntityFieldName(), DistributionSetFields.NAME.getJpaEntityFieldName());
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private final List<String> subEntityAttributes;
|
||||
|
||||
DistributionSetTagFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
DistributionSetTagFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = Collections.emptyList();
|
||||
}
|
||||
|
||||
DistributionSetTagFields(final String fieldName, final String... subEntityAttributes) {
|
||||
this.fieldName = fieldName;
|
||||
DistributionSetTagFields(final String jpaEntityFieldName, final String... subEntityAttributes) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = List.of(subEntityAttributes);
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,16 @@ import lombok.Getter;
|
||||
* the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum DistributionSetTypeFields implements FieldNameProvider {
|
||||
public enum DistributionSetTypeFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
KEY("key"),
|
||||
NAME("name"),
|
||||
DESCRIPTION("description");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
DistributionSetTypeFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
DistributionSetTypeFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,26 +18,26 @@ import java.util.List;
|
||||
* Describing the fields of the Rollout model which can be used in the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum RolloutFields implements FieldNameProvider {
|
||||
public enum RolloutFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
NAME("name"),
|
||||
DESCRIPTION("description"),
|
||||
STATUS("status"),
|
||||
DISTRIBUTIONSET("distributionSet", DistributionSetFields.ID.getFieldName(),
|
||||
DistributionSetFields.NAME.getFieldName(), DistributionSetFields.VERSION.getFieldName(),
|
||||
DistributionSetFields.TYPE.getFieldName());
|
||||
DISTRIBUTIONSET("distributionSet", DistributionSetFields.ID.getJpaEntityFieldName(),
|
||||
DistributionSetFields.NAME.getJpaEntityFieldName(), DistributionSetFields.VERSION.getJpaEntityFieldName(),
|
||||
DistributionSetFields.TYPE.getJpaEntityFieldName());
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private final List<String> subEntityAttributes;
|
||||
|
||||
RolloutFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
RolloutFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = Collections.emptyList();
|
||||
}
|
||||
|
||||
RolloutFields(final String fieldName, final String... subEntityAttributes) {
|
||||
this.fieldName = fieldName;
|
||||
RolloutFields(final String jpaEntityFieldName, final String... subEntityAttributes) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = List.of(subEntityAttributes);
|
||||
}
|
||||
}
|
||||
@@ -15,15 +15,15 @@ import lombok.Getter;
|
||||
* Describing the fields of the RolloutGroup model which can be used in the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum RolloutGroupFields implements FieldNameProvider {
|
||||
public enum RolloutGroupFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
NAME("name"),
|
||||
DESCRIPTION("description");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
RolloutGroupFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
RolloutGroupFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,13 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* An RSQL query field interface extended by all the fields that could be used in RSQL queries.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface FieldNameProvider {
|
||||
public interface RsqlQueryField {
|
||||
|
||||
/**
|
||||
* Separator for the sub attributes
|
||||
@@ -32,10 +30,10 @@ public interface FieldNameProvider {
|
||||
String SUB_ATTRIBUTE_SPLIT_REGEX = "\\" + SUB_ATTRIBUTE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* @return the string representation of the underlying persistence field
|
||||
* name e.g. in case of sorting. Never {@code null}.
|
||||
* @return the string representation of the underlying persistence field name e.g. in case of sorting.
|
||||
*/
|
||||
String getFieldName();
|
||||
@NotNull
|
||||
String getJpaEntityFieldName();
|
||||
|
||||
/**
|
||||
* Returns the sub attributes
|
||||
@@ -48,7 +46,7 @@ public interface FieldNameProvider {
|
||||
final String[] subAttributes = propertyFieldName.split(SUB_ATTRIBUTE_SPLIT_REGEX, 2);
|
||||
// [0] field name | [1] key name (could miss, e.g. for target attributes)
|
||||
final String mapKeyName = subAttributes.length == 2 ? subAttributes[1] : null;
|
||||
return ObjectUtils.isEmpty(mapKeyName) ? new String[] { getFieldName() } : new String[] { getFieldName(), mapKeyName };
|
||||
return ObjectUtils.isEmpty(mapKeyName) ? new String[] { getJpaEntityFieldName() } : new String[] { getJpaEntityFieldName(), mapKeyName };
|
||||
} else {
|
||||
return propertyFieldName.split(SUB_ATTRIBUTE_SPLIT_REGEX);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import java.util.Optional;
|
||||
* Describing the fields of the SoftwareModule model which can be used in the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum SoftwareModuleFields implements FieldNameProvider {
|
||||
public enum SoftwareModuleFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
TYPE("type.key"),
|
||||
@@ -28,15 +28,15 @@ public enum SoftwareModuleFields implements FieldNameProvider {
|
||||
VERSION("version"),
|
||||
METADATA("metadata", new SimpleImmutableEntry<>("key", "value"));
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private Entry<String, String> subEntityMapTuple;
|
||||
|
||||
SoftwareModuleFields(final String fieldName) {
|
||||
this(fieldName, null);
|
||||
SoftwareModuleFields(final String jpaEntityFieldName) {
|
||||
this(jpaEntityFieldName, null);
|
||||
}
|
||||
|
||||
SoftwareModuleFields(final String fieldName, final Entry<String, String> subEntityMapTuple) {
|
||||
this.fieldName = fieldName;
|
||||
SoftwareModuleFields(final String jpaEntityFieldName, final Entry<String, String> subEntityMapTuple) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityMapTuple = subEntityMapTuple;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,20 +15,20 @@ import lombok.Getter;
|
||||
* Sort fields for SoftwareModuleMetadata.
|
||||
*/
|
||||
@Getter
|
||||
public enum SoftwareModuleMetadataFields implements FieldNameProvider {
|
||||
public enum SoftwareModuleMetadataFields implements RsqlQueryField {
|
||||
|
||||
KEY("key"),
|
||||
VALUE("value"),
|
||||
TARGETVISIBLE("targetVisible");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
SoftwareModuleMetadataFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
SoftwareModuleMetadataFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifierFieldName() {
|
||||
return KEY.getFieldName();
|
||||
return KEY.getJpaEntityFieldName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import lombok.Getter;
|
||||
* Describing the fields of the SoftwareModuleType model which can be used in the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum SoftwareModuleTypeFields implements FieldNameProvider {
|
||||
public enum SoftwareModuleTypeFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
KEY("key"),
|
||||
@@ -23,9 +23,9 @@ public enum SoftwareModuleTypeFields implements FieldNameProvider {
|
||||
DESCRIPTION("description"),
|
||||
MAXASSIGNMENTS("maxAssignments");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
SoftwareModuleTypeFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
SoftwareModuleTypeFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ import lombok.Getter;
|
||||
* Describing the fields of the Tag model which can be used in the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum TagFields implements FieldNameProvider {
|
||||
public enum TagFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
NAME("name"),
|
||||
DESCRIPTION("description"),
|
||||
COLOUR("colour");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
TagFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
TagFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.Optional;
|
||||
* e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum TargetFields implements FieldNameProvider {
|
||||
public enum TargetFields implements RsqlQueryField {
|
||||
|
||||
ID("controllerId"),
|
||||
NAME("name"),
|
||||
@@ -38,26 +38,26 @@ public enum TargetFields implements FieldNameProvider {
|
||||
TAG("tags.name"),
|
||||
LASTCONTROLLERREQUESTAT("lastTargetQuery"),
|
||||
METADATA("metadata", new SimpleImmutableEntry<>("key", "value")),
|
||||
TARGETTYPE("targetType", TargetTypeFields.KEY.getFieldName(), TargetTypeFields.NAME.getFieldName());
|
||||
TARGETTYPE("targetType", TargetTypeFields.KEY.getJpaEntityFieldName(), TargetTypeFields.NAME.getJpaEntityFieldName());
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private final List<String> subEntityAttributes;
|
||||
private final Entry<String, String> subEntityMapTuple;
|
||||
|
||||
TargetFields(final String fieldName) {
|
||||
this(fieldName, Collections.emptyList(), null);
|
||||
TargetFields(final String jpaEntityFieldName) {
|
||||
this(jpaEntityFieldName, Collections.emptyList(), null);
|
||||
}
|
||||
|
||||
TargetFields(final String fieldName, final String... subEntityAttributes) {
|
||||
this(fieldName, List.of(subEntityAttributes), null);
|
||||
TargetFields(final String jpaEntityFieldName, final String... subEntityAttributes) {
|
||||
this(jpaEntityFieldName, List.of(subEntityAttributes), null);
|
||||
}
|
||||
|
||||
TargetFields(final String fieldName, final Entry<String, String> subEntityMapTuple) {
|
||||
this(fieldName, Collections.emptyList(), subEntityMapTuple);
|
||||
TargetFields(final String jpaEntityFieldName, final Entry<String, String> subEntityMapTuple) {
|
||||
this(jpaEntityFieldName, Collections.emptyList(), subEntityMapTuple);
|
||||
}
|
||||
|
||||
TargetFields(final String fieldName, final List<String> subEntityAttributes, final Entry<String, String> subEntityMapTuple) {
|
||||
this.fieldName = fieldName;
|
||||
TargetFields(final String jpaEntityFieldName, final List<String> subEntityAttributes, final Entry<String, String> subEntityMapTuple) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = subEntityAttributes;
|
||||
this.subEntityMapTuple = subEntityMapTuple;
|
||||
}
|
||||
|
||||
@@ -18,25 +18,25 @@ import java.util.List;
|
||||
* Describing the fields of the Target model which can be used in the REST API e.g. for sorting etc.
|
||||
*/
|
||||
@Getter
|
||||
public enum TargetFilterQueryFields implements FieldNameProvider {
|
||||
public enum TargetFilterQueryFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
NAME("name"),
|
||||
AUTOASSIGNDISTRIBUTIONSET("autoAssignDistributionSet", "name", "version");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
private List<String> subEntityAttributes;
|
||||
|
||||
TargetFilterQueryFields(final String fieldName) {
|
||||
this(fieldName, Collections.emptyList());
|
||||
TargetFilterQueryFields(final String jpaEntityFieldName) {
|
||||
this(jpaEntityFieldName, Collections.emptyList());
|
||||
}
|
||||
|
||||
TargetFilterQueryFields(final String fieldName, final String... subEntityAttribues) {
|
||||
this(fieldName, List.of(subEntityAttribues));
|
||||
TargetFilterQueryFields(final String jpaEntityFieldName, final String... subEntityAttribues) {
|
||||
this(jpaEntityFieldName, List.of(subEntityAttribues));
|
||||
}
|
||||
|
||||
TargetFilterQueryFields(final String fieldName, final List<String> subEntityAttribues) {
|
||||
this.fieldName = fieldName;
|
||||
TargetFilterQueryFields(final String jpaEntityFieldName, final List<String> subEntityAttribues) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
this.subEntityAttributes = subEntityAttribues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,19 +15,19 @@ import lombok.Getter;
|
||||
* Sort fields for TargetMetadata.
|
||||
*/
|
||||
@Getter
|
||||
public enum TargetMetadataFields implements FieldNameProvider {
|
||||
public enum TargetMetadataFields implements RsqlQueryField {
|
||||
|
||||
KEY("key"),
|
||||
VALUE("value");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
TargetMetadataFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
TargetMetadataFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifierFieldName() {
|
||||
return KEY.getFieldName();
|
||||
return KEY.getJpaEntityFieldName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,16 @@ import lombok.Getter;
|
||||
* Additionally, here were added fields for Target in order filtering over target fields also.
|
||||
*/
|
||||
@Getter
|
||||
public enum TargetTagFields implements FieldNameProvider {
|
||||
public enum TargetTagFields implements RsqlQueryField {
|
||||
|
||||
ID(TagFields.ID.getFieldName()),
|
||||
NAME(TagFields.NAME.getFieldName()),
|
||||
DESCRIPTION(TagFields.DESCRIPTION.getFieldName()),
|
||||
COLOUR(TagFields.COLOUR.getFieldName());
|
||||
ID(TagFields.ID.getJpaEntityFieldName()),
|
||||
NAME(TagFields.NAME.getJpaEntityFieldName()),
|
||||
DESCRIPTION(TagFields.DESCRIPTION.getJpaEntityFieldName()),
|
||||
COLOUR(TagFields.COLOUR.getJpaEntityFieldName());
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
TargetTagFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
TargetTagFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
@@ -15,16 +15,16 @@ import lombok.Getter;
|
||||
* Describing the fields of the TargetType model which can be used in the REST API
|
||||
*/
|
||||
@Getter
|
||||
public enum TargetTypeFields implements FieldNameProvider {
|
||||
public enum TargetTypeFields implements RsqlQueryField {
|
||||
|
||||
ID("id"),
|
||||
KEY("key"),
|
||||
NAME("name"),
|
||||
DESCRIPTION("description");
|
||||
|
||||
private final String fieldName;
|
||||
private final String jpaEntityFieldName;
|
||||
|
||||
TargetTypeFields(final String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
TargetTypeFields(final String jpaEntityFieldName) {
|
||||
this.jpaEntityFieldName = jpaEntityFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,16 +27,16 @@ public class FileNameFieldsTest {
|
||||
public void repositoryManagementMethodsArePreAuthorizedAnnotated() {
|
||||
final String packageName = getClass().getPackage().getName();
|
||||
try (final ScanResult scanResult = new ClassGraph().acceptPackages(packageName).scan()) {
|
||||
final List<? extends Class<? extends FieldNameProvider>> matchingClasses = scanResult.getAllClasses()
|
||||
final List<? extends Class<? extends RsqlQueryField>> matchingClasses = scanResult.getAllClasses()
|
||||
.stream()
|
||||
.filter(classInPackage -> classInPackage.implementsInterface(FieldNameProvider.class))
|
||||
.filter(classInPackage -> classInPackage.implementsInterface(RsqlQueryField.class))
|
||||
.map(ClassInfo::loadClass)
|
||||
.map(clazz -> (Class<? extends FieldNameProvider>) clazz)
|
||||
.map(clazz -> (Class<? extends RsqlQueryField>) clazz)
|
||||
.toList();
|
||||
assertThat(matchingClasses).isNotEmpty();
|
||||
matchingClasses.forEach(providerClass -> {
|
||||
assertThat(providerClass.getEnumConstants()).isNotEmpty();
|
||||
for (final FieldNameProvider provider : providerClass.getEnumConstants()) {
|
||||
for (final RsqlQueryField provider : providerClass.getEnumConstants()) {
|
||||
if (provider.isMap() && !provider.getSubEntityAttributes().isEmpty()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Currently sub-entity attributes for maps are not supported, alternatively you could use the key/value tuple, defined by SimpleImmutableEntry class");
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.rsql;
|
||||
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.Node;
|
||||
import cz.jirutka.rsql.parser.ast.RSQLVisitor;
|
||||
@@ -23,16 +23,16 @@ public interface RsqlVisitorFactory {
|
||||
|
||||
/**
|
||||
* Provides a {@link RSQLVisitor} instance for validating RSQL queries based
|
||||
* on the given {@link FieldNameProvider}.
|
||||
* on the given {@link RsqlQueryField}.
|
||||
*
|
||||
* @param <A>
|
||||
* The type of the {@link FieldNameProvider}.
|
||||
* The type of the {@link RsqlQueryField}.
|
||||
* @param fieldNameProvider
|
||||
* providing accessing to the relevant field names.
|
||||
*
|
||||
* @return An {@link RSQLVisitor} to validate the {@link Node}s of an RSQL
|
||||
* query.
|
||||
*/
|
||||
<A extends Enum<A> & FieldNameProvider> RSQLVisitor<Void, String> validationRsqlVisitor(Class<A> fieldNameProvider);
|
||||
<A extends Enum<A> & RsqlQueryField> RSQLVisitor<Void, String> validationRsqlVisitor(Class<A> fieldNameProvider);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,70 +15,83 @@ import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.ComparisonNode;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldNameProvider> {
|
||||
public abstract class AbstractRSQLVisitor<A extends Enum<A> & RsqlQueryField> {
|
||||
|
||||
private final Class<A> fieldNameProvider;
|
||||
|
||||
protected AbstractFieldNameRSQLVisitor(final Class<A> fieldNameProvider) {
|
||||
@Value
|
||||
public class RsqlField {
|
||||
|
||||
A enumValue;
|
||||
String[] subAttributes;
|
||||
|
||||
private RsqlField(final A enumValue, final String[] subAttributes) {
|
||||
this.enumValue = enumValue;
|
||||
this.subAttributes = subAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
protected AbstractRSQLVisitor(final Class<A> fieldNameProvider) {
|
||||
this.fieldNameProvider = fieldNameProvider;
|
||||
}
|
||||
|
||||
protected A getFieldEnumByName(final ComparisonNode node) {
|
||||
final String[] graph = node.getSelector().split(FieldNameProvider.SUB_ATTRIBUTE_SPLIT_REGEX);
|
||||
protected RsqlField getRsqlField(final ComparisonNode node) {
|
||||
final String[] graph = node.getSelector().split(RsqlQueryField.SUB_ATTRIBUTE_SPLIT_REGEX);
|
||||
final String enumName = graph.length == 0 ? node.getSelector() : graph[0];
|
||||
log.debug("get field identifier by name {} of enum type {}", enumName, fieldNameProvider);
|
||||
|
||||
try {
|
||||
return Enum.valueOf(fieldNameProvider, enumName.toUpperCase());
|
||||
final A enumValue = Enum.valueOf(fieldNameProvider, enumName.toUpperCase());
|
||||
final String[] subAttributes = enumValue.getSubAttributes(node.getSelector());
|
||||
|
||||
// validate
|
||||
if (enumValue.isMap()) {
|
||||
// enum.key
|
||||
if (subAttributes.length != 2) {
|
||||
throw new RSQLParameterUnsupportedFieldException(
|
||||
"The syntax of the given map search parameter field {" + node.getSelector() + "} is wrong. Syntax is: <enum name>.<key name>");
|
||||
}
|
||||
} else {
|
||||
// sub entity need minimum 1 dot
|
||||
if (!enumValue.getSubEntityAttributes().isEmpty() && subAttributes.length < 2) {
|
||||
throw createRSQLParameterUnsupportedException(node, null);
|
||||
}
|
||||
}
|
||||
|
||||
// build property and validate sub attributes
|
||||
final StringBuilder fieldNameBuilder = new StringBuilder(enumValue.getJpaEntityFieldName());
|
||||
for (int i = 1; i < subAttributes.length; i++) {
|
||||
final String propertyField = getFormattedSubEntityAttribute(enumValue, subAttributes[i]);
|
||||
|
||||
if (!enumValue.containsSubEntityAttribute(propertyField)) {
|
||||
if (i != subAttributes.length - 1 || !enumValue.isMap()) {
|
||||
throw createRSQLParameterUnsupportedException(node, null);
|
||||
} // otherwise - the key of map is not in the sub entity attributes
|
||||
}
|
||||
|
||||
fieldNameBuilder.append(RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR).append(propertyField);
|
||||
}
|
||||
|
||||
return new RsqlField(enumValue, enumValue.getSubAttributes(fieldNameBuilder.toString()));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw createRSQLParameterUnsupportedException(node, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
|
||||
final String[] subAttributes = propertyEnum.getSubAttributes(node.getSelector());
|
||||
|
||||
if (propertyEnum.isMap()) {
|
||||
// enum.key
|
||||
if (subAttributes.length != 2) {
|
||||
throw new RSQLParameterUnsupportedFieldException(
|
||||
"The syntax of the given map search parameter field {" + node.getSelector() + "} is wrong. Syntax is: <enum name>.<key name>");
|
||||
}
|
||||
} else {
|
||||
// sub entity need minimum 1 dot
|
||||
if (!propertyEnum.getSubEntityAttributes().isEmpty() && subAttributes.length < 2) {
|
||||
throw createRSQLParameterUnsupportedException(node, null);
|
||||
}
|
||||
}
|
||||
|
||||
final StringBuilder fieldNameBuilder = new StringBuilder(propertyEnum.getFieldName());
|
||||
for (int i = 1; i < subAttributes.length; i++) {
|
||||
final String propertyField = getFormattedSubEntityAttribute(propertyEnum, subAttributes[i]);
|
||||
|
||||
if (!propertyEnum.containsSubEntityAttribute(propertyField)) {
|
||||
if (i != subAttributes.length - 1 || !propertyEnum.isMap()) {
|
||||
throw createRSQLParameterUnsupportedException(node, null);
|
||||
} // otherwise - the key of map is not in the sub entity attributes
|
||||
}
|
||||
|
||||
fieldNameBuilder.append(FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR).append(propertyField);
|
||||
}
|
||||
|
||||
return fieldNameBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node current processing node
|
||||
* @param rootException in case there is a cause otherwise {@code null}
|
||||
* @return Exception with prepared message extracted from the comparison node.
|
||||
*/
|
||||
protected RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(
|
||||
private RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(
|
||||
@NotNull final ComparisonNode node,
|
||||
final Exception rootException) {
|
||||
return new RSQLParameterUnsupportedFieldException(String.format(
|
||||
@@ -97,7 +110,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
||||
.filter(enumField -> enumField.getSubEntityAttributes().isEmpty()).map(enumField -> {
|
||||
final String enumFieldName = enumField.name().toLowerCase();
|
||||
if (enumField.isMap()) {
|
||||
return enumFieldName + FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR + "keyName";
|
||||
return enumFieldName + RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR + "keyName";
|
||||
} else {
|
||||
return enumFieldName;
|
||||
}
|
||||
@@ -107,7 +120,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
||||
.filter(enumField -> !enumField.getSubEntityAttributes().isEmpty()).flatMap(enumField -> {
|
||||
final List<String> subEntity = enumField
|
||||
.getSubEntityAttributes().stream().map(fieldName -> enumField.name().toLowerCase()
|
||||
+ FieldNameProvider.SUB_ATTRIBUTE_SEPARATOR + fieldName)
|
||||
+ RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR + fieldName)
|
||||
.toList();
|
||||
|
||||
return subEntity.stream();
|
||||
@@ -9,19 +9,19 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactory;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.RSQLVisitor;
|
||||
|
||||
/**
|
||||
* Factory providing {@link RSQLVisitor} instances which validate the nodes
|
||||
* based on a given {@link FieldNameProvider}.
|
||||
* based on a given {@link RsqlQueryField}.
|
||||
*/
|
||||
public class DefaultRsqlVisitorFactory implements RsqlVisitorFactory {
|
||||
|
||||
@Override
|
||||
public <A extends Enum<A> & FieldNameProvider> RSQLVisitor<Void, String> validationRsqlVisitor(
|
||||
public <A extends Enum<A> & RsqlQueryField> RSQLVisitor<Void, String> validationRsqlVisitor(
|
||||
final Class<A> fieldNameProvider) {
|
||||
return new FieldValidationRsqlVisitor<>(fieldNameProvider);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.AndNode;
|
||||
import cz.jirutka.rsql.parser.ast.ComparisonNode;
|
||||
@@ -19,19 +19,19 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor;
|
||||
|
||||
/**
|
||||
* {@link RSQLVisitor} implementation which validates the nodes (fields) based
|
||||
* on a given {@link FieldNameProvider} for a given entity type.
|
||||
* on a given {@link RsqlQueryField} for a given entity type.
|
||||
*
|
||||
* @param <A>
|
||||
* The type the {@link FieldNameProvider} refers to.
|
||||
* The type the {@link RsqlQueryField} refers to.
|
||||
*/
|
||||
public class FieldValidationRsqlVisitor<A extends Enum<A> & FieldNameProvider> extends AbstractFieldNameRSQLVisitor<A>
|
||||
public class FieldValidationRsqlVisitor<A extends Enum<A> & RsqlQueryField> extends AbstractRSQLVisitor<A>
|
||||
implements RSQLVisitor<Void, String> {
|
||||
|
||||
/**
|
||||
* Constructs the visitor and initializes it.
|
||||
*
|
||||
* @param fieldNameProvider
|
||||
* The {@link FieldNameProvider} to use for validation.
|
||||
* The {@link RsqlQueryField} to use for validation.
|
||||
*/
|
||||
public FieldValidationRsqlVisitor(final Class<A> fieldNameProvider) {
|
||||
super(fieldNameProvider);
|
||||
@@ -49,8 +49,8 @@ public class FieldValidationRsqlVisitor<A extends Enum<A> & FieldNameProvider> e
|
||||
|
||||
@Override
|
||||
public Void visit(final ComparisonNode node, final String param) {
|
||||
final A fieldName = getFieldEnumByName(node);
|
||||
getAndValidatePropertyFieldName(fieldName, node);
|
||||
// get AND validates
|
||||
getRsqlField(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import cz.jirutka.rsql.parser.ast.OrNode;
|
||||
import cz.jirutka.rsql.parser.ast.RSQLVisitor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.FieldValueConverter;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
@@ -66,7 +66,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@Slf4j
|
||||
public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> extends AbstractFieldNameRSQLVisitor<A>
|
||||
public class JpaQueryRsqlVisitor<A extends Enum<A> & RsqlQueryField, T> extends AbstractRSQLVisitor<A>
|
||||
implements RSQLVisitor<List<Predicate>, String> {
|
||||
|
||||
public static final Character LIKE_WILDCARD = '*';
|
||||
@@ -171,13 +171,12 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
* @param enumField
|
||||
* field from a FieldNameProvider to resolve on the persistence
|
||||
* layer
|
||||
* @param finalProperty
|
||||
* dot notated field path
|
||||
* @param rsqlField RSQL field
|
||||
* @return the Path for a field
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Path<Object> getFieldPath(final A enumField, final String finalProperty) {
|
||||
return (Path<Object>) getFieldPath(root, enumField.getSubAttributes(finalProperty), enumField.isMap(),
|
||||
private Path<Object> getFieldPath(final A enumField, final RsqlField rsqlField) {
|
||||
return (Path<Object>) getFieldPath(root, rsqlField.getSubAttributes(), enumField.isMap(),
|
||||
this::getJoinFieldPath).orElseThrow(
|
||||
() -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", null));
|
||||
}
|
||||
@@ -218,20 +217,19 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public List<Predicate> visit(final ComparisonNode node, final String param) {
|
||||
final A fieldName = getFieldEnumByName(node);
|
||||
final String finalProperty = getAndValidatePropertyFieldName(fieldName, node);
|
||||
final RsqlField rsqlField = getRsqlField(node);
|
||||
|
||||
final List<String> values = node.getArguments();
|
||||
final List<Object> transformedValues = new ArrayList<>();
|
||||
final Path<Object> fieldPath = getFieldPath(fieldName, finalProperty);
|
||||
final Path<Object> fieldPath = getFieldPath(rsqlField.getEnumValue(), rsqlField);
|
||||
|
||||
for (final String value : values) {
|
||||
transformedValues.add(convertValueIfNecessary(node, fieldName, value, fieldPath));
|
||||
transformedValues.add(convertValueIfNecessary(node, rsqlField.getEnumValue(), value, fieldPath));
|
||||
}
|
||||
|
||||
this.joinsNeeded = this.joinsNeeded || areJoinsNeeded(node);
|
||||
|
||||
return mapToPredicate(node, fieldPath, node.getArguments(), transformedValues, fieldName, finalProperty);
|
||||
return mapToPredicate(node, fieldPath, node.getArguments(), transformedValues, rsqlField);
|
||||
}
|
||||
|
||||
private static boolean areJoinsNeeded(final ComparisonNode node) {
|
||||
@@ -307,8 +305,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
}
|
||||
|
||||
private List<Predicate> mapToPredicate(final ComparisonNode node, final Path<Object> fieldPath,
|
||||
final List<String> values, final List<Object> transformedValues, final A enumField,
|
||||
final String finalProperty) {
|
||||
final List<String> values, final List<Object> transformedValues, final RsqlField rsqlField) {
|
||||
|
||||
String value = values.get(0);
|
||||
// if lookup is available, replace macros ...
|
||||
@@ -316,16 +313,16 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
value = virtualPropertyReplacer.replace(value);
|
||||
}
|
||||
|
||||
final Predicate mapPredicate = mapToMapPredicate(node, fieldPath, enumField);
|
||||
final Predicate mapPredicate = mapToMapPredicate(node, fieldPath, rsqlField.getEnumValue());
|
||||
|
||||
final Predicate valuePredicate = addOperatorPredicate(node, getMapValueFieldPath(enumField, fieldPath),
|
||||
transformedValues, value, finalProperty, enumField);
|
||||
final Predicate valuePredicate = addOperatorPredicate(node, getMapValueFieldPath(rsqlField.getEnumValue(), fieldPath),
|
||||
transformedValues, value, rsqlField);
|
||||
|
||||
return toSingleList(mapPredicate != null ? cb.and(mapPredicate, valuePredicate) : valuePredicate);
|
||||
}
|
||||
|
||||
private Predicate addOperatorPredicate(final ComparisonNode node, final Path<Object> fieldPath,
|
||||
final List<Object> transformedValues, final String value, final String finalProperty, final A enumField) {
|
||||
final List<Object> transformedValues, final String value, final RsqlField rsqlField) {
|
||||
|
||||
// only 'equal' and 'notEqual' can handle transformed value like
|
||||
// enums. The JPA API cannot handle object types for greaterThan etc
|
||||
@@ -337,7 +334,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
case "==":
|
||||
return getEqualToPredicate(transformedValue, fieldPath);
|
||||
case "!=":
|
||||
return getNotEqualToPredicate(transformedValue, fieldPath, finalProperty, enumField);
|
||||
return getNotEqualToPredicate(transformedValue, fieldPath, rsqlField);
|
||||
case "=gt=":
|
||||
return cb.greaterThan(pathOfString(fieldPath), value);
|
||||
case "=ge=":
|
||||
@@ -349,7 +346,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
case "=in=":
|
||||
return in(pathOfString(fieldPath), transformedValues);
|
||||
case "=out=":
|
||||
return getOutPredicate(transformedValues, finalProperty, enumField, fieldPath);
|
||||
return getOutPredicate(transformedValues, rsqlField, fieldPath);
|
||||
default:
|
||||
throw new RSQLParameterSyntaxException(
|
||||
"operator symbol {" + operator + "} is either not supported or not implemented");
|
||||
@@ -357,18 +354,18 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
}
|
||||
|
||||
private Predicate getOutPredicate(
|
||||
final List<Object> transformedValues, final String finalProperty,
|
||||
final A enumField, final Path<Object> fieldPath) {
|
||||
final String[] fieldNames = enumField.getSubAttributes(finalProperty);
|
||||
final List<Object> transformedValues,
|
||||
final RsqlField rsqlField, final Path<Object> fieldPath) {
|
||||
final String[] fieldNames = rsqlField.getSubAttributes();
|
||||
|
||||
if (isSimpleField(fieldNames, enumField.isMap())) {
|
||||
if (isSimpleField(fieldNames, rsqlField.getEnumValue().isMap())) {
|
||||
final Path<String> pathOfString = pathOfString(fieldPath);
|
||||
return cb.or(cb.isNull(pathOfString), cb.not(in(pathOfString, transformedValues)));
|
||||
}
|
||||
|
||||
clearOuterJoinsIfNotNeeded();
|
||||
|
||||
return toNotExistsSubQueryPredicate(fieldNames, enumField, expressionToCompare -> in(expressionToCompare, transformedValues));
|
||||
return toNotExistsSubQueryPredicate(fieldNames, rsqlField.getEnumValue(), expressionToCompare -> in(expressionToCompare, transformedValues));
|
||||
}
|
||||
|
||||
private Path<Object> getMapValueFieldPath(final A enumField, final Path<Object> fieldPath) {
|
||||
@@ -422,7 +419,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
}
|
||||
|
||||
private Predicate getNotEqualToPredicate(final Object transformedValue, final Path<Object> fieldPath,
|
||||
final String finalProperty, final A enumField) {
|
||||
final RsqlField rsqlField) {
|
||||
|
||||
if (transformedValue == null) {
|
||||
return cb.isNotNull(pathOfString(fieldPath));
|
||||
@@ -433,9 +430,9 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
return cb.and(cb.isNotNull(pathOfString(fieldPath)), cb.notEqual(pathOfString(fieldPath), ""));
|
||||
}
|
||||
|
||||
final String[] fieldNames = enumField.getSubAttributes(finalProperty);
|
||||
final String[] fieldNames = rsqlField.getSubAttributes();
|
||||
|
||||
if (isSimpleField(fieldNames, enumField.isMap())) {
|
||||
if (isSimpleField(fieldNames, rsqlField.getEnumValue().isMap())) {
|
||||
if (isPattern(transformedValueStr)) { // a pattern, use like
|
||||
return cb.or(cb.isNull(pathOfString(fieldPath)), notLike(pathOfString(fieldPath), toSQL(transformedValueStr)));
|
||||
} else {
|
||||
@@ -446,9 +443,9 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
clearOuterJoinsIfNotNeeded();
|
||||
|
||||
if (isPattern(transformedValueStr)) { // a pattern, use like
|
||||
return toNotExistsSubQueryPredicate(fieldNames, enumField, expressionToCompare -> like(expressionToCompare, toSQL(transformedValueStr)));
|
||||
return toNotExistsSubQueryPredicate(fieldNames, rsqlField.getEnumValue(), expressionToCompare -> like(expressionToCompare, toSQL(transformedValueStr)));
|
||||
} else {
|
||||
return toNotExistsSubQueryPredicate(fieldNames, enumField, expressionToCompare -> equal(expressionToCompare, transformedValueStr));
|
||||
return toNotExistsSubQueryPredicate(fieldNames, rsqlField.getEnumValue(), expressionToCompare -> equal(expressionToCompare, transformedValueStr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import jakarta.persistence.metamodel.Type;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.FieldValueConverter;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
@@ -57,8 +57,8 @@ import org.springframework.util.ObjectUtils;
|
||||
* @param <T> the entity type referenced by the root
|
||||
*/
|
||||
@Slf4j
|
||||
public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
extends AbstractFieldNameRSQLVisitor<A> implements RSQLVisitor<List<Predicate>, String> {
|
||||
public class JpaQueryRsqlVisitorG2<A extends Enum<A> & RsqlQueryField, T>
|
||||
extends AbstractRSQLVisitor<A> implements RSQLVisitor<List<Predicate>, String> {
|
||||
|
||||
public static final Character LIKE_WILDCARD = '*';
|
||||
private static final char ESCAPE_CHAR = '\\';
|
||||
@@ -110,31 +110,30 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
|
||||
@Override
|
||||
public List<Predicate> visit(final ComparisonNode node, final String param) {
|
||||
final A fieldName = getFieldEnumByName(node);
|
||||
final String finalProperty = getAndValidatePropertyFieldName(fieldName, node);
|
||||
final RsqlField rsqlField = getRsqlField(node);
|
||||
|
||||
final List<String> values = node.getArguments();
|
||||
final List<Object> transformedValues = new ArrayList<>();
|
||||
final Path<Object> fieldPath = getFieldPath(root, fieldName.getSubAttributes(finalProperty), fieldName.isMap());
|
||||
final Path<Object> fieldPath = getFieldPath(root, rsqlField);
|
||||
|
||||
for (final String value : values) {
|
||||
transformedValues.add(convertValueIfNecessary(node, fieldName, fieldPath, value));
|
||||
transformedValues.add(convertValueIfNecessary(node, rsqlField.getEnumValue(), fieldPath, value));
|
||||
}
|
||||
|
||||
this.joinsNeeded = this.joinsNeeded || areJoinsNeeded(node);
|
||||
|
||||
return mapToPredicate(node, fieldName, finalProperty, fieldPath, node.getArguments(), transformedValues);
|
||||
return mapToPredicate(node, rsqlField, fieldPath, node.getArguments(), transformedValues);
|
||||
}
|
||||
|
||||
private List<Predicate> mapToPredicate(final ComparisonNode node, final A enumField, final String finalProperty,
|
||||
private List<Predicate> mapToPredicate(final ComparisonNode node, final RsqlField rsqlField,
|
||||
final Path<Object> fieldPath,
|
||||
final List<String> values, final List<Object> transformedValues) {
|
||||
// if lookup is available, replace macros ...
|
||||
final String value = virtualPropertyReplacer == null ? values.get(0) : virtualPropertyReplacer.replace(values.get(0));
|
||||
|
||||
final Predicate mapPredicate = mapToMapPredicate(node, enumField, fieldPath);
|
||||
final Predicate valuePredicate = addOperatorPredicate(node, enumField, finalProperty,
|
||||
getValueFieldPath(enumField, fieldPath), transformedValues, value);
|
||||
final Predicate mapPredicate = mapToMapPredicate(node, rsqlField.getEnumValue(), fieldPath);
|
||||
final Predicate valuePredicate = addOperatorPredicate(node, rsqlField,
|
||||
getValueFieldPath(rsqlField.getEnumValue(), fieldPath), transformedValues, value);
|
||||
|
||||
return Collections.singletonList(mapPredicate != null ? cb.and(mapPredicate, valuePredicate) : valuePredicate);
|
||||
}
|
||||
@@ -165,7 +164,7 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
"SimpleImmutableEntry are allowed. Neither of those could be found!"));
|
||||
return equal(fieldPath.get(keyFieldName), keyValue);
|
||||
}
|
||||
private Predicate addOperatorPredicate(final ComparisonNode node, final A enumField, final String finalProperty,
|
||||
private Predicate addOperatorPredicate(final ComparisonNode node, final RsqlField rsqlField,
|
||||
final Path<Object> fieldPath, final List<Object> transformedValues, final String value) {
|
||||
// only 'equal' and 'notEqual' can handle transformed value like enums.
|
||||
// The JPA API cannot handle object types for greaterThan etc. methods.
|
||||
@@ -173,13 +172,13 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
final String operator = node.getOperator().getSymbol();
|
||||
return switch (operator) {
|
||||
case "==" -> getEqualToPredicate(fieldPath, transformedValue);
|
||||
case "!=" -> getNotEqualToPredicate(enumField, finalProperty, fieldPath, transformedValue);
|
||||
case "!=" -> getNotEqualToPredicate(rsqlField, fieldPath, transformedValue);
|
||||
case "=gt=" -> cb.greaterThan(pathOfString(fieldPath), value);
|
||||
case "=ge=" -> cb.greaterThanOrEqualTo(pathOfString(fieldPath), value);
|
||||
case "=lt=" -> cb.lessThan(pathOfString(fieldPath), value);
|
||||
case "=le=" -> cb.lessThanOrEqualTo(pathOfString(fieldPath), value);
|
||||
case "=in=" -> in(pathOfString(fieldPath), transformedValues);
|
||||
case "=out=" -> getOutPredicate(enumField, finalProperty, fieldPath, transformedValues);
|
||||
case "=out=" -> getOutPredicate(rsqlField, fieldPath, transformedValues);
|
||||
default -> throw new RSQLParameterSyntaxException(
|
||||
"Operator symbol {" + operator + "} is either not supported or not implemented");
|
||||
};
|
||||
@@ -204,7 +203,7 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
return cb.equal(fieldPath, transformedValue);
|
||||
}
|
||||
|
||||
private Predicate getNotEqualToPredicate(final A enumField, final String finalProperty,
|
||||
private Predicate getNotEqualToPredicate(final RsqlField rsqlField,
|
||||
final Path<Object> fieldPath, final Object transformedValue) {
|
||||
if (transformedValue == null) {
|
||||
return cb.isNotNull(fieldPath);
|
||||
@@ -215,9 +214,9 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
return cb.and(cb.isNotNull(fieldPath), cb.notEqual(pathOfString(fieldPath), ""));
|
||||
}
|
||||
|
||||
final String[] fieldNames = enumField.getSubAttributes(finalProperty);
|
||||
final String[] fieldNames = rsqlField.getSubAttributes();
|
||||
|
||||
if (isSimpleField(fieldNames, enumField.isMap())) {
|
||||
if (isSimpleField(fieldNames, rsqlField.getEnumValue().isMap())) {
|
||||
if (isPattern(transformedValueStr)) { // a pattern, use like
|
||||
return cb.or(cb.isNull(fieldPath), notLike(pathOfString(fieldPath), toSQL(transformedValueStr)));
|
||||
} else {
|
||||
@@ -226,7 +225,7 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
}
|
||||
|
||||
clearJoinsIfNotNeeded();
|
||||
return toNotExistsSubQueryPredicate(enumField, fieldNames, expressionToCompare ->
|
||||
return toNotExistsSubQueryPredicate(rsqlField, expressionToCompare ->
|
||||
isPattern(transformedValueStr) ? // a pattern, use like
|
||||
like(expressionToCompare, toSQL(transformedValueStr)) :
|
||||
equal(expressionToCompare, transformedValueStr));
|
||||
@@ -235,23 +234,22 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
return toNullOrNotEqualPredicate(fieldPath, transformedValue);
|
||||
}
|
||||
|
||||
private Predicate getOutPredicate(final A enumField, final String finalProperty, final Path<Object> fieldPath,
|
||||
private Predicate getOutPredicate(final RsqlField rsqlField, final Path<Object> fieldPath,
|
||||
final List<Object> transformedValues) {
|
||||
final String[] fieldNames = enumField.getSubAttributes(finalProperty);
|
||||
final String[] subAttributes = rsqlField.getSubAttributes();
|
||||
|
||||
if (isSimpleField(fieldNames, enumField.isMap())) {
|
||||
if (isSimpleField(subAttributes, rsqlField.getEnumValue().isMap())) {
|
||||
return cb.or(cb.isNull(fieldPath), cb.not(in(pathOfString(fieldPath), transformedValues)));
|
||||
}
|
||||
|
||||
clearJoinsIfNotNeeded();
|
||||
return toNotExistsSubQueryPredicate(enumField, fieldNames,
|
||||
expressionToCompare -> in(expressionToCompare, transformedValues));
|
||||
return toNotExistsSubQueryPredicate(rsqlField, expressionToCompare -> in(expressionToCompare, transformedValues));
|
||||
}
|
||||
|
||||
private Path<Object> getFieldPath(
|
||||
final Root<?> root, final String[] split, final boolean isMapKeyField) {
|
||||
private Path<Object> getFieldPath(final Root<?> root, final RsqlField rsqlField) {
|
||||
final String[] split = rsqlField.getSubAttributes();
|
||||
Path<Object> fieldPath = null;
|
||||
for (int i = 0, end = isMapKeyField ? split.length - 1 : split.length; i < end; i++) {
|
||||
for (int i = 0, end = rsqlField.getEnumValue().isMap() ? split.length - 1 : split.length; i < end; i++) {
|
||||
final String fieldNameSplit = split[i];
|
||||
fieldPath = fieldPath == null ? getPath(root, fieldNameSplit) : fieldPath.get(fieldNameSplit);
|
||||
}
|
||||
@@ -360,14 +358,14 @@ public class JpaQueryRsqlVisitorG2<A extends Enum<A> & FieldNameProvider, T>
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Predicate toNotExistsSubQueryPredicate(final A enumField, final String[] fieldNames, final Function<Expression<String>, Predicate> subQueryPredicateProvider) {
|
||||
private Predicate toNotExistsSubQueryPredicate(final RsqlField rsqlField, final Function<Expression<String>, Predicate> subQueryPredicateProvider) {
|
||||
final Class<?> javaType = root.getJavaType();
|
||||
final Subquery<?> subquery = query.subquery(javaType);
|
||||
final Root subqueryRoot = subquery.from(javaType);
|
||||
final Predicate equalPredicate = cb.equal(root.get(enumField.identifierFieldName()),
|
||||
subqueryRoot.get(enumField.identifierFieldName()));
|
||||
final Expression<String> expressionToCompare = getExpressionToCompare(enumField,
|
||||
getFieldPath(subqueryRoot, fieldNames, enumField.isMap()));
|
||||
final Predicate equalPredicate = cb.equal(root.get(rsqlField.getEnumValue().identifierFieldName()),
|
||||
subqueryRoot.get(rsqlField.getEnumValue().identifierFieldName()));
|
||||
final Expression<String> expressionToCompare = getExpressionToCompare(rsqlField.getEnumValue(),
|
||||
getFieldPath(subqueryRoot, rsqlField));
|
||||
final Predicate subQueryPredicate = subQueryPredicateProvider.apply(expressionToCompare);
|
||||
subquery.select(subqueryRoot).where(cb.and(equalPredicate, subQueryPredicate));
|
||||
return cb.not(cb.exists(subquery));
|
||||
|
||||
@@ -22,7 +22,7 @@ import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.text.StrLookup;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder;
|
||||
@@ -82,7 +82,7 @@ public final class RSQLUtility {
|
||||
* given RSQL query.
|
||||
*
|
||||
* @param rsql the rsql query to be parsed
|
||||
* @param fieldNameProvider the enum class type which implements the {@link FieldNameProvider}
|
||||
* @param fieldNameProvider the enum class type which implements the {@link RsqlQueryField}
|
||||
* @param virtualPropertyReplacer holds the logic how the known macros have to be resolved; may be <code>null</code>
|
||||
* @param database database in use
|
||||
*
|
||||
@@ -91,7 +91,7 @@ public final class RSQLUtility {
|
||||
* given {@code fieldNameProvider}
|
||||
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
||||
*/
|
||||
public static <A extends Enum<A> & FieldNameProvider, T> Specification<T> buildRsqlSpecification(
|
||||
public static <A extends Enum<A> & RsqlQueryField, T> Specification<T> buildRsqlSpecification(
|
||||
final String rsql, final Class<A> fieldNameProvider,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) {
|
||||
return new RSQLSpecification<>(rsql, fieldNameProvider, virtualPropertyReplacer, database);
|
||||
@@ -106,7 +106,7 @@ public final class RSQLUtility {
|
||||
* @throws RSQLParserException if RSQL syntax is invalid
|
||||
* @throws RSQLParameterUnsupportedFieldException if RSQL key is not allowed
|
||||
*/
|
||||
public static <A extends Enum<A> & FieldNameProvider> void validateRsqlFor(
|
||||
public static <A extends Enum<A> & RsqlQueryField> void validateRsqlFor(
|
||||
final String rsql, final Class<A> fieldNameProvider) {
|
||||
final RSQLVisitor<Void, String> visitor =
|
||||
RsqlConfigHolder.getInstance().getRsqlVisitorFactory().validationRsqlVisitor(fieldNameProvider);
|
||||
@@ -127,7 +127,7 @@ public final class RSQLUtility {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RSQLSpecification<A extends Enum<A> & FieldNameProvider, T> implements Specification<T> {
|
||||
private static final class RSQLSpecification<A extends Enum<A> & RsqlQueryField, T> implements Specification<T> {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -1196,7 +1196,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
+ "from target/controller. Expected behaviour is that in case of OK finished update the target will go to "
|
||||
+ "IN_SYNC status and installed DS is set to the assigned DS entry.")
|
||||
void assignDistributionSetAndAddFinishedActionStatus() {
|
||||
final PageRequest pageRequest = PageRequest.of(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName());
|
||||
final PageRequest pageRequest = PageRequest.of(0, 100, Direction.ASC, ActionStatusFields.ID.getJpaEntityFieldName());
|
||||
|
||||
final DeploymentResult deployResWithDsA = prepareComplexRepo("undep-A-T", 2, "dep-A-T", 4, 1, "dsA");
|
||||
final DeploymentResult deployResWithDsB = prepareComplexRepo("undep-B-T", 3, "dep-B-T", 5, 1, "dsB");
|
||||
|
||||
@@ -19,7 +19,7 @@ import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.persistence.config.PersistenceUnitProperties;
|
||||
@@ -39,11 +39,11 @@ public class RSQLToSQL {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
public <T, A extends Enum<A> & FieldNameProvider> String toSQL(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final boolean legacyRsqlVisitor) {
|
||||
public <T, A extends Enum<A> & RsqlQueryField> String toSQL(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final boolean legacyRsqlVisitor) {
|
||||
return createDbQuery(domainClass, fieldsClass, rsql, legacyRsqlVisitor).getSQLString();
|
||||
}
|
||||
|
||||
public <T, A extends Enum<A> & FieldNameProvider> DatabaseQuery createDbQuery(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final boolean legacyRsqlVisitor) {
|
||||
public <T, A extends Enum<A> & RsqlQueryField> DatabaseQuery createDbQuery(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final boolean legacyRsqlVisitor) {
|
||||
final CriteriaQuery<T> query = createQuery(domainClass, fieldsClass, rsql, legacyRsqlVisitor);
|
||||
final TypedQuery<?> typedQuery = entityManager.createQuery(query);
|
||||
// executes the query - otherwise the SQL string is not generated
|
||||
@@ -52,7 +52,7 @@ public class RSQLToSQL {
|
||||
return typedQuery.unwrap(JpaQuery.class).getDatabaseQuery();
|
||||
}
|
||||
|
||||
private <T, A extends Enum<A> & FieldNameProvider> CriteriaQuery<T> createQuery(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final boolean legacyRsqlVisitor) {
|
||||
private <T, A extends Enum<A> & RsqlQueryField> CriteriaQuery<T> createQuery(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql, final boolean legacyRsqlVisitor) {
|
||||
final CriteriaQuery<T> query = entityManager.getCriteriaBuilder().createQuery(domainClass);
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
return query.where(
|
||||
@@ -65,7 +65,7 @@ public class RSQLToSQL {
|
||||
);
|
||||
}
|
||||
|
||||
private <T, A extends Enum<A> & FieldNameProvider> Predicate toPredicate(
|
||||
private <T, A extends Enum<A> & RsqlQueryField> Predicate toPredicate(
|
||||
final String rsql,
|
||||
final Class<A> fieldsClass, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final Root<T> root, final CriteriaQuery<?> query, final CriteriaBuilder cb,
|
||||
|
||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
@@ -52,7 +52,7 @@ public class RSQLToSQLTest {
|
||||
print(JpaTarget.class, TargetFields.class, "(tag!=TAG1 or tag !=TAG2)");
|
||||
}
|
||||
|
||||
private <T, A extends Enum<A> & FieldNameProvider> void print(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql) {
|
||||
private <T, A extends Enum<A> & RsqlQueryField> void print(final Class<T> domainClass, final Class<A> fieldsClass, final String rsql) {
|
||||
System.out.println(rsql);
|
||||
System.out.println("\tlegacy:\n" +
|
||||
"\t\t" + rsqlToSQL.toSQL(domainClass, fieldsClass, rsql, true));
|
||||
|
||||
@@ -38,7 +38,7 @@ import jakarta.persistence.metamodel.EntityType;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import jakarta.persistence.metamodel.Type;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
@@ -554,7 +554,7 @@ public class RSQLUtilityTest {
|
||||
return (Path<Y>) path;
|
||||
}
|
||||
|
||||
private enum TestFieldEnum implements FieldNameProvider {
|
||||
private enum TestFieldEnum implements RsqlQueryField {
|
||||
TESTFIELD("testfield"), TESTFIELD_WITH_SUB_ENTITIES("testfieldWithSubEntities", "subentity11", "subentity22");
|
||||
|
||||
private final String fieldName;
|
||||
@@ -570,7 +570,7 @@ public class RSQLUtilityTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFieldName() {
|
||||
public String getJpaEntityFieldName() {
|
||||
return this.fieldName;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public final class MgmtTargetMapper {
|
||||
.withRel(MgmtRestConstants.TARGET_V1_ATTRIBUTES).expand());
|
||||
response.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionHistory(response.getControllerId(), 0,
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE,
|
||||
ActionFields.ID.getFieldName() + ":" + SortDirection.DESC, null))
|
||||
ActionFields.ID.getJpaEntityFieldName() + ":" + SortDirection.DESC, null))
|
||||
.withRel(MgmtRestConstants.TARGET_V1_ACTIONS).expand());
|
||||
response.add(linkTo(methodOn(MgmtTargetRestApi.class).getMetadata(response.getControllerId(),
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET_VALUE,
|
||||
@@ -316,7 +316,7 @@ public final class MgmtTargetMapper {
|
||||
|
||||
result.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionStatusList(controllerId, action.getId(), 0,
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE,
|
||||
ActionStatusFields.ID.getFieldName() + ":" + SortDirection.DESC))
|
||||
ActionStatusFields.ID.getJpaEntityFieldName() + ":" + SortDirection.DESC))
|
||||
.withRel(MgmtRestConstants.TARGET_V1_ACTION_STATUS).expand());
|
||||
|
||||
final Rollout rollout = action.getRollout();
|
||||
|
||||
@@ -58,7 +58,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeTargetSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, TargetFields.CONTROLLERID.getFieldName());
|
||||
return Sort.by(Direction.ASC, TargetFields.CONTROLLERID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(TargetFields.class, sortParam));
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeTargetTypeSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, TargetTypeFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, TargetTypeFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(TargetTypeFields.class, sortParam));
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeTagSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, TagFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, TagFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(TagFields.class, sortParam));
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeTargetFilterQuerySortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, TargetFilterQueryFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, TargetFilterQueryFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(TargetFilterQueryFields.class, sortParam));
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeSoftwareModuleSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, SoftwareModuleFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, SoftwareModuleFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(SoftwareModuleFields.class, sortParam));
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeSoftwareModuleTypeSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, SoftwareModuleTypeFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, SoftwareModuleTypeFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(SoftwareModuleTypeFields.class, sortParam));
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeDistributionSetSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, DistributionSetFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, DistributionSetFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(DistributionSetFields.class, sortParam));
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeDistributionSetTypeSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, DistributionSetTypeFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, DistributionSetTypeFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(DistributionSetTypeFields.class, sortParam));
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public final class PagingUtility {
|
||||
if (sortParam == null) {
|
||||
// default sort is DESC in case of action to match behavior
|
||||
// of management UI (last entry on top)
|
||||
return Sort.by(Direction.DESC, ActionFields.ID.getFieldName());
|
||||
return Sort.by(Direction.DESC, ActionFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(ActionFields.class, sortParam));
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public final class PagingUtility {
|
||||
if (sortParam == null) {
|
||||
// default sort is DESC in case of action status to match behavior
|
||||
// of management UI (last entry on top)
|
||||
return Sort.by(Direction.DESC, ActionStatusFields.ID.getFieldName());
|
||||
return Sort.by(Direction.DESC, ActionStatusFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(ActionStatusFields.class, sortParam));
|
||||
}
|
||||
@@ -140,7 +140,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeDistributionSetMetadataSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, DistributionSetMetadataFields.KEY.getFieldName());
|
||||
return Sort.by(Direction.ASC, DistributionSetMetadataFields.KEY.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(DistributionSetMetadataFields.class, sortParam));
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeSoftwareModuleMetadataSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, SoftwareModuleMetadataFields.KEY.getFieldName());
|
||||
return Sort.by(Direction.ASC, SoftwareModuleMetadataFields.KEY.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(SoftwareModuleMetadataFields.class, sortParam));
|
||||
}
|
||||
@@ -156,7 +156,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeRolloutSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, RolloutFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, RolloutFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(RolloutFields.class, sortParam));
|
||||
}
|
||||
@@ -164,7 +164,7 @@ public final class PagingUtility {
|
||||
static Sort sanitizeRolloutGroupSortParam(final String sortParam) {
|
||||
if (sortParam == null) {
|
||||
// default
|
||||
return Sort.by(Direction.ASC, RolloutGroupFields.ID.getFieldName());
|
||||
return Sort.by(Direction.ASC, RolloutGroupFields.ID.getJpaEntityFieldName());
|
||||
}
|
||||
return Sort.by(SortUtility.parse(RolloutGroupFields.class, sortParam));
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
assertThat(actions).hasSize(2);
|
||||
updateActionStatus(actions.get(0), Status.FINISHED, null, "test");
|
||||
|
||||
final PageRequest pageRequest = PageRequest.of(0, 1000, Direction.ASC, ActionFields.ID.getFieldName());
|
||||
final PageRequest pageRequest = PageRequest.of(0, 1000, Direction.ASC, ActionFields.ID.getJpaEntityFieldName());
|
||||
final Action action = deploymentManagement.findActionsByTarget(knownTargetId, pageRequest).getContent().get(0);
|
||||
|
||||
final ActionStatus status = deploymentManagement.findActionStatusByAction(PAGE, action.getId()).getContent()
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.rest.exception.SortParameterSyntaxErrorException;
|
||||
import org.eclipse.hawkbit.rest.exception.SortParameterUnsupportedDirectionException;
|
||||
import org.eclipse.hawkbit.rest.exception.SortParameterUnsupportedFieldException;
|
||||
@@ -53,11 +53,11 @@ public final class SortUtility {
|
||||
* should be related to.
|
||||
* @param <T>
|
||||
* the type of the enumeration which must be derived from
|
||||
* {@link FieldNameProvider}
|
||||
* {@link RsqlQueryField}
|
||||
* @param sortString
|
||||
* the string representation of the query parameters. Might be
|
||||
* {@code null} or an empty string.
|
||||
* @return a list which holds the {@link FieldNameProvider} and the specific
|
||||
* @return a list which holds the {@link RsqlQueryField} and the specific
|
||||
* {@link Direction} for them as a tuple. Never {@code null}. In
|
||||
* case of no sorting parameters an empty map will be returned.
|
||||
* @throws SortParameterSyntaxErrorException
|
||||
@@ -67,7 +67,7 @@ public final class SortUtility {
|
||||
* @throws SortParameterUnsupportedDirectionException
|
||||
* if the given direction is not "ASC" or "DESC"
|
||||
*/
|
||||
public static <T extends Enum<T> & FieldNameProvider> List<Order> parse(final Class<T> enumType,
|
||||
public static <T extends Enum<T> & RsqlQueryField> List<Order> parse(final Class<T> enumType,
|
||||
final String sortString) throws SortParameterSyntaxErrorException {
|
||||
final List<Order> parsedSortings = new ArrayList<>();
|
||||
// scan the sort tuples e.g. field:direction
|
||||
@@ -84,7 +84,7 @@ public final class SortUtility {
|
||||
final T identifier = getAttributeIdentifierByName(enumType, fieldName);
|
||||
|
||||
final Direction sortDirection = getDirection(sortDirectionStr);
|
||||
parsedSortings.add(new Order(sortDirection, identifier.getFieldName()));
|
||||
parsedSortings.add(new Order(sortDirection, identifier.getJpaEntityFieldName()));
|
||||
} else {
|
||||
throw new SortParameterSyntaxErrorException();
|
||||
}
|
||||
@@ -103,12 +103,12 @@ public final class SortUtility {
|
||||
* the name of the enum
|
||||
* @param <T>
|
||||
* the type of the enumeration which must be derived from
|
||||
* {@link FieldNameProvider}
|
||||
* {@link RsqlQueryField}
|
||||
* @return the corresponding enum
|
||||
* @throws SortParameterUnsupportedFieldException
|
||||
* if there is no matching enum for the specified name
|
||||
*/
|
||||
private static <T extends Enum<T> & FieldNameProvider> T getAttributeIdentifierByName(final Class<T> enumType,
|
||||
private static <T extends Enum<T> & RsqlQueryField> T getAttributeIdentifierByName(final Class<T> enumType,
|
||||
final String name) {
|
||||
try {
|
||||
return Enum.valueOf(enumType, name.toUpperCase());
|
||||
|
||||
Reference in New Issue
Block a user