diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index 287581d297..9c285fa9ee 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -82,6 +82,7 @@ import org.thingsboard.server.common.data.kv.TimeseriesSaveResult; import org.thingsboard.server.common.data.mobile.app.MobileApp; import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.query.EntityKeyValueType; import org.thingsboard.server.common.data.queue.ProcessingStrategy; import org.thingsboard.server.common.data.queue.ProcessingStrategyType; import org.thingsboard.server.common.data.queue.Queue; @@ -456,6 +457,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmConditionFilter temperatureAlarmFlagFilter = new AlarmConditionFilter(); temperatureAlarmFlagFilter.setArgument("temperatureAlarmFlag"); + temperatureAlarmFlagFilter.setValueType(EntityKeyValueType.BOOLEAN); BooleanFilterPredicate temperatureAlarmFlagAttributePredicate = new BooleanFilterPredicate(); temperatureAlarmFlagAttributePredicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL); temperatureAlarmFlagAttributePredicate.setValue(new AlarmConditionValue<>(Boolean.TRUE, null)); @@ -463,6 +465,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmConditionFilter temperatureFilter = new AlarmConditionFilter(); temperatureFilter.setArgument("temperature"); + temperatureFilter.setValueType(EntityKeyValueType.NUMERIC); NumericFilterPredicate temperatureFilterPredicate = new NumericFilterPredicate(); temperatureFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); temperatureFilterPredicate.setValue(new AlarmConditionValue<>(null, "temperatureAlarmThreshold")); @@ -479,6 +482,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmConditionFilter clearTemperatureFilter = new AlarmConditionFilter(); clearTemperatureFilter.setArgument("temperature"); + clearTemperatureFilter.setValueType(EntityKeyValueType.NUMERIC); NumericFilterPredicate clearTemperatureFilterPredicate = new NumericFilterPredicate(); clearTemperatureFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.LESS_OR_EQUAL); clearTemperatureFilterPredicate.setValue(new AlarmConditionValue<>(null, "temperatureAlarmThreshold")); @@ -517,6 +521,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmConditionFilter humidityAlarmFlagAttributeFilter = new AlarmConditionFilter(); humidityAlarmFlagAttributeFilter.setArgument("humidityAlarmFlag"); + humidityAlarmFlagAttributeFilter.setValueType(EntityKeyValueType.BOOLEAN); BooleanFilterPredicate humidityAlarmFlagPredicate = new BooleanFilterPredicate(); humidityAlarmFlagPredicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL); humidityAlarmFlagPredicate.setValue(new AlarmConditionValue<>(Boolean.TRUE, null)); @@ -524,6 +529,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmConditionFilter humidityFilter = new AlarmConditionFilter(); humidityFilter.setArgument("humidity"); + humidityFilter.setValueType(EntityKeyValueType.NUMERIC); NumericFilterPredicate humidityFilterPredicate = new NumericFilterPredicate(); humidityFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.LESS); humidityFilterPredicate.setValue(new AlarmConditionValue<>(null, "humidityAlarmThreshold")); @@ -540,6 +546,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmConditionFilter clearHumidityFilter = new AlarmConditionFilter(); clearHumidityFilter.setArgument("humidity"); + clearHumidityFilter.setValueType(EntityKeyValueType.NUMERIC); NumericFilterPredicate clearHumidityFilterPredicate = new NumericFilterPredicate(); clearHumidityFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER_OR_EQUAL); clearHumidityFilterPredicate.setValue(new AlarmConditionValue<>(null, "humidityAlarmThreshold")); diff --git a/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java b/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java index f71bdd02a8..652e69781d 100644 --- a/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java +++ b/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java @@ -62,6 +62,7 @@ import org.thingsboard.server.common.data.id.CalculatedFieldId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EventId; +import org.thingsboard.server.common.data.query.EntityKeyValueType; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.event.EventDao; import org.thingsboard.server.dao.service.DaoSqlTest; @@ -167,6 +168,7 @@ public class AlarmRulesTest extends AbstractControllerTest { SimpleAlarmConditionExpression simpleExpression = new SimpleAlarmConditionExpression(); AlarmConditionFilter filter = new AlarmConditionFilter(); filter.setArgument("temperature"); + filter.setValueType(EntityKeyValueType.NUMERIC); NumericFilterPredicate predicate = new NumericFilterPredicate(); predicate.setOperation(NumericOperation.GREATER_OR_EQUAL); AlarmConditionValue thresholdValue = new AlarmConditionValue<>(); @@ -854,6 +856,7 @@ public class AlarmRulesTest extends AbstractControllerTest { SimpleAlarmConditionExpression simpleExpression = new SimpleAlarmConditionExpression(); AlarmConditionFilter filter = new AlarmConditionFilter(); filter.setArgument(argument); + filter.setValueType(EntityKeyValueType.STRING); StringFilterPredicate predicate = new StringFilterPredicate(); predicate.setOperation(stringOperation); predicate.setValue(conditionValue); diff --git a/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java b/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java index 209a2da6f1..8cf9c307a6 100644 --- a/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java @@ -1025,8 +1025,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes cf.setConfigurationVersion(1); PropagationCalculatedFieldConfiguration cfg = new PropagationCalculatedFieldConfiguration(); - cfg.setDirection(EntitySearchDirection.TO); - cfg.setRelationType(EntityRelation.CONTAINS_TYPE); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.TO, EntityRelation.CONTAINS_TYPE)); cfg.setApplyExpressionToResolvedArguments(true); Argument arg = new Argument(); @@ -1105,8 +1104,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes cf.setConfigurationVersion(1); PropagationCalculatedFieldConfiguration cfg = new PropagationCalculatedFieldConfiguration(); - cfg.setDirection(EntitySearchDirection.TO); - cfg.setRelationType(EntityRelation.CONTAINS_TYPE); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.TO, EntityRelation.CONTAINS_TYPE)); cfg.setApplyExpressionToResolvedArguments(false); // arguments-only mode Argument arg = new Argument(); diff --git a/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java index aa3e802f70..4ebace6ae7 100644 --- a/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java @@ -271,8 +271,7 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest { private CalculatedFieldConfiguration getPropagationCalculatedFieldConfig(Map arguments) { var config = new PropagationCalculatedFieldConfiguration(); - config.setRelationType(EntityRelation.CONTAINS_TYPE); - config.setDirection(EntitySearchDirection.TO); + config.setRelation(new RelationPathLevel(EntitySearchDirection.TO, EntityRelation.CONTAINS_TYPE)); config.setApplyExpressionToResolvedArguments(false); config.setExpression(null); diff --git a/application/src/test/java/org/thingsboard/server/service/cf/ctx/state/PropagationCalculatedFieldStateTest.java b/application/src/test/java/org/thingsboard/server/service/cf/ctx/state/PropagationCalculatedFieldStateTest.java index 04a7ab5203..4f8b14f9b5 100644 --- a/application/src/test/java/org/thingsboard/server/service/cf/ctx/state/PropagationCalculatedFieldStateTest.java +++ b/application/src/test/java/org/thingsboard/server/service/cf/ctx/state/PropagationCalculatedFieldStateTest.java @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.DoubleDataEntry; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.common.data.relation.RelationPathLevel; import org.thingsboard.server.common.stats.DefaultStatsFactory; import org.thingsboard.server.dao.usagerecord.ApiLimitService; import org.thingsboard.server.service.cf.PropagationCalculatedFieldResult; @@ -222,8 +223,7 @@ public class PropagationCalculatedFieldStateTest { private CalculatedFieldConfiguration getCalculatedFieldConfig(boolean applyExpressionToResolvedArguments) { var config = new PropagationCalculatedFieldConfiguration(); - config.setDirection(EntitySearchDirection.TO); - config.setRelationType(EntityRelation.CONTAINS_TYPE); + config.setRelation(new RelationPathLevel(EntitySearchDirection.TO, EntityRelation.CONTAINS_TYPE)); config.setApplyExpressionToResolvedArguments(applyExpressionToResolvedArguments); Argument temperatureArg = new Argument(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/rule/condition/expression/AlarmConditionFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/rule/condition/expression/AlarmConditionFilter.java index e9785d675b..6a1a36cf35 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/rule/condition/expression/AlarmConditionFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/rule/condition/expression/AlarmConditionFilter.java @@ -20,6 +20,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.thingsboard.server.common.data.alarm.rule.condition.expression.predicate.KeyFilterPredicate; +import org.thingsboard.server.common.data.query.EntityKeyValueType; import java.io.Serializable; @@ -28,6 +29,8 @@ public class AlarmConditionFilter implements Serializable { @NotBlank private String argument; + @NotNull + private EntityKeyValueType valueType; @Valid @NotNull private KeyFilterPredicate predicate; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfiguration.java index 5e8c822d78..61d4542eb9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfiguration.java @@ -15,13 +15,12 @@ */ package org.thingsboard.server.common.data.cf.configuration; -import jakarta.validation.constraints.NotBlank; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.cf.CalculatedFieldType; -import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationPathLevel; import java.util.List; @@ -32,10 +31,9 @@ public class PropagationCalculatedFieldConfiguration extends BaseCalculatedField public static final String PROPAGATION_CONFIG_ARGUMENT = "propagationCtx"; + @Valid @NotNull - private EntitySearchDirection direction; - @NotBlank - private String relationType; + private RelationPathLevel relation; private boolean applyExpressionToResolvedArguments; @@ -77,7 +75,7 @@ public class PropagationCalculatedFieldConfiguration extends BaseCalculatedField public Argument toPropagationArgument() { var refDynamicSourceConfiguration = new RelationPathQueryDynamicSourceConfiguration(); - refDynamicSourceConfiguration.setLevels(List.of(new RelationPathLevel(direction, relationType))); + refDynamicSourceConfiguration.setLevels(List.of(relation)); var propagationArgument = new Argument(); propagationArgument.setRefDynamicSourceConfiguration(refDynamicSourceConfiguration); return propagationArgument; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationPathLevel.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationPathLevel.java index c28135204f..c04ca09e79 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationPathLevel.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationPathLevel.java @@ -15,9 +15,11 @@ */ package org.thingsboard.server.common.data.relation; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import org.thingsboard.server.common.data.StringUtils; -public record RelationPathLevel(EntitySearchDirection direction, String relationType) { +public record RelationPathLevel(@NotNull EntitySearchDirection direction, @NotBlank String relationType) { public void validate() { if (direction == null) { diff --git a/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfigurationTest.java b/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfigurationTest.java index 36f63feed7..9c77f1bd21 100644 --- a/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfigurationTest.java +++ b/common/data/src/test/java/org/thingsboard/server/common/data/cf/configuration/PropagationCalculatedFieldConfigurationTest.java @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.cf.CalculatedFieldType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.common.data.relation.RelationPathLevel; import java.util.Map; import java.util.UUID; @@ -71,7 +72,7 @@ public class PropagationCalculatedFieldConfigurationTest { assertThatThrownBy(cfg::validate) .isInstanceOf(IllegalArgumentException.class) .hasMessage("At least one argument must be configured with the 'Current entity' " + - "source entity type for 'Expression result' propagation mode!"); + "source entity type for 'Expression result' propagation mode!"); } @Test @@ -95,6 +96,7 @@ public class PropagationCalculatedFieldConfigurationTest { @Test void validateShouldThrowWhenReferencedEntityKeyIsNotSet() { var cfg = new PropagationCalculatedFieldConfiguration(); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.TO, EntityRelation.CONTAINS_TYPE)); Argument argument = new Argument(); cfg.setArguments(Map.of("someArgumentName", argument)); assertThatThrownBy(cfg::validate) @@ -128,8 +130,7 @@ public class PropagationCalculatedFieldConfigurationTest { @Test void validateToPropagationArgumentMethodCallReturnCorrectArgument() { var cfg = new PropagationCalculatedFieldConfiguration(); - cfg.setDirection(EntitySearchDirection.TO); - cfg.setRelationType(EntityRelation.CONTAINS_TYPE); + cfg.setRelation(new RelationPathLevel(EntitySearchDirection.TO, EntityRelation.CONTAINS_TYPE)); Argument propagationArgument = cfg.toPropagationArgument(); assertThat(propagationArgument).isNotNull();