Browse Source

updated metric default value to double and added logic to handle relations when direction to

pull/14770/head
IrynaMatveieva 7 months ago
parent
commit
7a638c2151
  1. 22
      application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java
  2. 16
      application/src/main/java/org/thingsboard/server/service/cf/AbstractCalculatedFieldProcessingService.java
  3. 18
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/RelatedEntitiesAggregationCalculatedFieldState.java
  4. 23
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/RelatedEntitiesArgumentEntry.java
  5. 4
      application/src/main/java/org/thingsboard/server/utils/CalculatedFieldArgumentUtils.java
  6. 4
      application/src/test/java/org/thingsboard/server/cf/EntityAggregationCalculatedFieldTest.java
  7. 2
      application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java
  8. 2
      common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/AggMetric.java
  9. 6
      dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java

22
application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java

@ -595,22 +595,12 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware
Predicate<EntityId> matchesCfEntity = relatedEntity -> cfEntityId.equals(relatedEntity) || cfEntityId.equals(getProfileId(tenantId, relatedEntity));
if (byRelationPathQuery != null && !byRelationPathQuery.isEmpty()) {
switch (relation.direction()) {
case FROM -> {
if (byRelationPathQuery.size() > 1) {
throw new IllegalStateException("More than one relation found with direction 'TO' " +
"for relation type '" + relation.relationType() + "'. Found: " + byRelationPathQuery.size());
}
EntityRelation entityRelation = byRelationPathQuery.get(0); // only one supported
EntityId relatedId = entityRelation.getFrom();
if (matchesCfEntity.test(relatedId)) {
result.add(new CalculatedFieldEntityCtxId(tenantId, cf.getCfId(), relatedId));
}
}
case TO -> {
byRelationPathQuery.stream()
.filter(entityRelation -> matchesCfEntity.test(entityRelation.getTo()))
.forEach(entityRelation -> result.add(new CalculatedFieldEntityCtxId(tenantId, cf.getCfId(), entityRelation.getTo())));
}
case FROM -> byRelationPathQuery.stream()
.filter(entityRelation -> matchesCfEntity.test(entityRelation.getFrom()))
.forEach(entityRelation -> result.add(new CalculatedFieldEntityCtxId(tenantId, cf.getCfId(), entityRelation.getFrom())));
case TO -> byRelationPathQuery.stream()
.filter(entityRelation -> matchesCfEntity.test(entityRelation.getTo()))
.forEach(entityRelation -> result.add(new CalculatedFieldEntityCtxId(tenantId, cf.getCfId(), entityRelation.getTo())));
}
}
}

16
application/src/main/java/org/thingsboard/server/service/cf/AbstractCalculatedFieldProcessingService.java

@ -247,20 +247,8 @@ public abstract class AbstractCalculatedFieldProcessingService {
}
return switch (relation.direction()) {
case FROM -> relations.stream()
.map(EntityRelation::getTo)
.toList();
case TO -> {
if (relations.size() > 1) {
throw new IllegalStateException("More than one relation found with direction 'TO' " +
"for relation type '" + relation.relationType() + "'. Found: " + relations.size());
}
yield relations.stream()
.map(EntityRelation::getFrom)
.findFirst()
.map(List::of)
.orElseGet(Collections::emptyList);
}
case FROM -> relations.stream().map(EntityRelation::getTo).toList();
case TO -> relations.stream().map(EntityRelation::getFrom).toList();
};
}, calculatedFieldCallbackExecutor);
}

18
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/RelatedEntitiesAggregationCalculatedFieldState.java

@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.cf.configuration.aggregation.AggKeyInp
import org.thingsboard.server.common.data.cf.configuration.aggregation.AggMetric;
import org.thingsboard.server.common.data.cf.configuration.aggregation.RelatedEntitiesAggregationCalculatedFieldConfiguration;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.service.cf.CalculatedFieldResult;
import org.thingsboard.server.service.cf.TelemetryCalculatedFieldResult;
@ -300,8 +301,25 @@ public class RelatedEntitiesAggregationCalculatedFieldState extends BaseCalculat
if (argumentEntry == null || argumentEntry.isEmpty()) {
return ReadinessStatus.notReady(MISSING_AGGREGATION_ENTITIES_ERROR);
}
if (argumentEntry instanceof RelatedEntitiesArgumentEntry relatedEntitiesArgumentEntry) {
try {
checkConstraintByDirection(relatedEntitiesArgumentEntry);
} catch (Exception e) {
return ReadinessStatus.notReady(e.getMessage());
}
}
}
return ReadinessStatus.READY;
}
public void checkConstraintByDirection(RelatedEntitiesArgumentEntry relatedEntitiesArgumentEntry) {
if (ctx.getCalculatedField().getConfiguration() instanceof RelatedEntitiesAggregationCalculatedFieldConfiguration config) {
if (EntitySearchDirection.TO == config.getRelation().direction()) {
if (relatedEntitiesArgumentEntry.getEntityInputs().size() > 1) {
throw new IllegalArgumentException("More than one related entity is not supported for relation direction 'TO'. Found: " + relatedEntitiesArgumentEntry.getEntityInputs().size() + ".");
}
}
}
}
}

23
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/RelatedEntitiesArgumentEntry.java

@ -66,29 +66,28 @@ public class RelatedEntitiesArgumentEntry implements ArgumentEntry, HasLatestTs
@Override
public boolean updateEntry(ArgumentEntry entry, CalculatedFieldCtx ctx) {
if (entry instanceof RelatedEntitiesArgumentEntry relatedEntitiesArgumentEntry) {
checkMaxRelatedEntitiesPerArgument(ctx);
checkRelatedEntitiesNumber(ctx);
entityInputs.putAll(relatedEntitiesArgumentEntry.entityInputs);
return true;
} else if (entry instanceof SingleValueArgumentEntry singleValueArgumentEntry) {
if (entry.isForceResetPrevious()) {
checkMaxRelatedEntitiesPerArgument(ctx);
checkRelatedEntitiesNumber(ctx);
entityInputs.put(singleValueArgumentEntry.getEntityId(), singleValueArgumentEntry);
return true;
}
ArgumentEntry argumentEntry = entityInputs.get(singleValueArgumentEntry.getEntityId());
if (argumentEntry != null) {
argumentEntry.updateEntry(singleValueArgumentEntry, ctx);
} else {
checkMaxRelatedEntitiesPerArgument(ctx);
entityInputs.put(singleValueArgumentEntry.getEntityId(), singleValueArgumentEntry);
ArgumentEntry argumentEntry = entityInputs.get(singleValueArgumentEntry.getEntityId());
if (argumentEntry != null) {
argumentEntry.updateEntry(singleValueArgumentEntry, ctx);
} else {
checkRelatedEntitiesNumber(ctx);
entityInputs.put(singleValueArgumentEntry.getEntityId(), singleValueArgumentEntry);
}
}
return true;
} else {
throw new IllegalArgumentException("Unsupported argument entry type for aggregation argument entry: " + entry.getType());
}
return true;
}
private void checkMaxRelatedEntitiesPerArgument(CalculatedFieldCtx ctx) {
private void checkRelatedEntitiesNumber(CalculatedFieldCtx ctx) {
if (entityInputs.size() >= ctx.getMaxRelatedEntitiesPerCfArgument()) {
throw new IllegalArgumentException(
"Exceeded the maximum allowed related entities per argument '"

4
application/src/main/java/org/thingsboard/server/utils/CalculatedFieldArgumentUtils.java

@ -68,9 +68,9 @@ public class CalculatedFieldArgumentUtils {
}
public static ArgumentEntry createDefaultMetricArgumentEntry(String argKey, AggMetric metric) {
Long defaultValue = metric.getDefaultValue();
Double defaultValue = metric.getDefaultValue();
if (defaultValue != null) {
return ArgumentEntry.createSingleValueArgument(new DoubleDataEntry(argKey, defaultValue.doubleValue()));
return ArgumentEntry.createSingleValueArgument(new DoubleDataEntry(argKey, defaultValue));
}
return new SingleValueArgumentEntry();
}

4
application/src/test/java/org/thingsboard/server/cf/EntityAggregationCalculatedFieldTest.java

@ -254,7 +254,7 @@ public class EntityAggregationCalculatedFieldTest extends AbstractControllerTest
AggMetric consumption = new AggMetric();
consumption.setFunction(AggFunction.SUM);
consumption.setInput(new AggKeyInput("en"));
consumption.setDefaultValue(9999L);
consumption.setDefaultValue(9999.0);
aggMetrics.put("consumption", consumption);
AggMetric avgEnergyConsumption = new AggMetric();
@ -319,7 +319,7 @@ public class EntityAggregationCalculatedFieldTest extends AbstractControllerTest
AggMetric consumption = new AggMetric();
consumption.setFunction(AggFunction.SUM);
consumption.setInput(new AggKeyInput("en"));
consumption.setDefaultValue(9999L);
consumption.setDefaultValue(9999.0);
aggMetrics.put("consumption", consumption);
AggMetric avgTemperature = new AggMetric();

2
application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java

@ -382,7 +382,7 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest {
AggMetric metric = new AggMetric();
metric.setInput(new AggKeyInput("en"));
metric.setDefaultValue(9999L);
metric.setDefaultValue(9999.0);
config.setMetrics(Map.of("consumption", metric));
config.setWatermark(new Watermark(TimeUnit.DAYS.toSeconds(1)));

2
common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/aggregation/AggMetric.java

@ -27,6 +27,6 @@ public class AggMetric {
private AggFunction function;
private String filter;
private AggInput input;
private Long defaultValue;
private Double defaultValue;
}

6
dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java

@ -52,11 +52,11 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.eventsourcing.RelationActionEvent;
import org.thingsboard.server.exception.DataValidationException;
import org.thingsboard.server.dao.service.ConstraintValidator;
import org.thingsboard.server.dao.sql.JpaExecutorService;
import org.thingsboard.server.dao.sql.relation.JpaRelationQueryExecutorService;
import org.thingsboard.server.dao.usagerecord.ApiLimitService;
import org.thingsboard.server.exception.DataValidationException;
import java.util.ArrayList;
import java.util.Collections;
@ -547,7 +547,9 @@ class BaseRelationService implements RelationService {
case FROM -> findByFromAndType(tenantId, relationPathQuery.rootEntityId(), relationPathLevel.relationType(), RelationTypeGroup.COMMON);
case TO -> findByToAndType(tenantId, relationPathQuery.rootEntityId(), relationPathLevel.relationType(), RelationTypeGroup.COMMON);
};
return relations.size() > limit ? relations.subList(0, limit) : relations;
ArrayList<EntityRelation> entityRelations = new ArrayList<>(relations);
entityRelations.sort(Comparator.comparing(r -> r.getFrom().getId()));
return entityRelations.size() > limit ? entityRelations.subList(0, limit) : entityRelations;
}
return relationDao.findByRelationPathQuery(tenantId, relationPathQuery, limit);
}

Loading…
Cancel
Save