ZoneGroups from list to map

This commit is contained in:
dshvaika 2025-09-11 18:04:40 +03:00
parent b54906a9ef
commit ad0b6017e6
9 changed files with 53 additions and 104 deletions

View File

@ -42,7 +42,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.cf.configuration.geofencing.EntityCoordinates.ENTITY_ID_LATITUDE_ARGUMENT_KEY;
@ -124,10 +123,7 @@ public class GeofencingCalculatedFieldState extends BaseCalculatedFieldState {
Coordinates entityCoordinates = new Coordinates(latitude, longitude);
var geofencingCfg = (GeofencingCalculatedFieldConfiguration) ctx.getCalculatedField().getConfiguration();
Map<String, ZoneGroupConfiguration> zoneGroups = geofencingCfg
.getZoneGroups()
.stream()
.collect(Collectors.toMap(ZoneGroupConfiguration::getName, Function.identity()));
Map<String, ZoneGroupConfiguration> zoneGroups = geofencingCfg.getZoneGroups();
ObjectNode resultNode = JacksonUtil.newObjectNode();
List<ListenableFuture<Boolean>> relationFutures = new ArrayList<>();

View File

@ -51,7 +51,6 @@ import org.thingsboard.server.controller.CalculatedFieldControllerTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -674,7 +673,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
cfg.setEntityCoordinates(entityCoordinates);
// Zone groups: ATTRIBUTE on specific assets (one zone per group)
ZoneGroupConfiguration allowedZonesGroup = new ZoneGroupConfiguration("allowedZones", "zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration allowedZonesGroup = new ZoneGroupConfiguration("zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var allowedZoneDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
allowedZoneDynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
allowedZoneDynamicSourceConfiguration.setRelationType("AllowedZone");
@ -682,7 +681,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
allowedZoneDynamicSourceConfiguration.setFetchLastLevelOnly(true);
allowedZonesGroup.setRefDynamicSourceConfiguration(allowedZoneDynamicSourceConfiguration);
ZoneGroupConfiguration restrictedZonesGroup = new ZoneGroupConfiguration("restrictedZones", "zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration restrictedZonesGroup = new ZoneGroupConfiguration("zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var restrictedZoneDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
restrictedZoneDynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
restrictedZoneDynamicSourceConfiguration.setRelationType("RestrictedZone");
@ -690,7 +689,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
restrictedZoneDynamicSourceConfiguration.setFetchLastLevelOnly(true);
restrictedZonesGroup.setRefDynamicSourceConfiguration(restrictedZoneDynamicSourceConfiguration);
cfg.setZoneGroups(List.of(allowedZonesGroup, restrictedZonesGroup));
cfg.setZoneGroups(Map.of("allowedZones", allowedZonesGroup, "restrictedZones", restrictedZonesGroup));
// Output to server attributes
Output out = new Output();
@ -783,14 +782,14 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
GeofencingCalculatedFieldConfiguration cfg = new GeofencingCalculatedFieldConfiguration();
cfg.setEntityCoordinates(new EntityCoordinates(ENTITY_ID_LATITUDE_ARGUMENT_KEY, ENTITY_ID_LONGITUDE_ARGUMENT_KEY));
var allowedZonesGroup = new ZoneGroupConfiguration("allowedZones", "zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var allowedZonesGroup = new ZoneGroupConfiguration("zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var allowedZoneDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
allowedZoneDynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
allowedZoneDynamicSourceConfiguration.setRelationType("AllowedZone");
allowedZoneDynamicSourceConfiguration.setMaxLevel(1);
allowedZoneDynamicSourceConfiguration.setFetchLastLevelOnly(true);
allowedZonesGroup.setRefDynamicSourceConfiguration(allowedZoneDynamicSourceConfiguration);
cfg.setZoneGroups(List.of(allowedZonesGroup));
cfg.setZoneGroups(Map.of("allowedZones", allowedZonesGroup));
// Server attributes output
Output out = new Output();

View File

@ -452,7 +452,7 @@ public class GeofencingCalculatedFieldStateTest {
EntityCoordinates entityCoordinates = new EntityCoordinates("latitude", "longitude");
config.setEntityCoordinates(entityCoordinates);
ZoneGroupConfiguration allowedZonesGroup = new ZoneGroupConfiguration("allowedZones", "zone", reportStrategy, true);
ZoneGroupConfiguration allowedZonesGroup = new ZoneGroupConfiguration("zone", reportStrategy, true);
var allowedZoneDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
allowedZoneDynamicSourceConfiguration.setDirection(EntitySearchDirection.TO);
allowedZoneDynamicSourceConfiguration.setRelationType("AllowedZone");
@ -462,7 +462,7 @@ public class GeofencingCalculatedFieldStateTest {
allowedZonesGroup.setRelationType("CurrentZone");
allowedZonesGroup.setDirection(EntitySearchDirection.TO);
ZoneGroupConfiguration restrictedZonesGroup = new ZoneGroupConfiguration("restrictedZones", "zone", reportStrategy, true);
ZoneGroupConfiguration restrictedZonesGroup = new ZoneGroupConfiguration("zone", reportStrategy, true);
var restrictedZoneDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
restrictedZoneDynamicSourceConfiguration.setDirection(EntitySearchDirection.TO);
restrictedZoneDynamicSourceConfiguration.setRelationType("RestrictedZone");
@ -472,7 +472,7 @@ public class GeofencingCalculatedFieldStateTest {
restrictedZonesGroup.setRelationType("CurrentZone");
restrictedZonesGroup.setDirection(EntitySearchDirection.TO);
config.setZoneGroups(List.of(allowedZonesGroup, restrictedZonesGroup));
config.setZoneGroups(Map.of("allowedZones", allowedZonesGroup, "restrictedZones", restrictedZonesGroup));
Output output = new Output();
output.setType(OutputType.TIME_SERIES);

View File

@ -25,17 +25,15 @@ import org.thingsboard.server.common.data.cf.configuration.ScheduledUpdateSuppor
import org.thingsboard.server.common.data.id.EntityId;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@Data
public class GeofencingCalculatedFieldConfiguration implements ArgumentsBasedCalculatedFieldConfiguration, ScheduledUpdateSupportedCalculatedFieldConfiguration {
private EntityCoordinates entityCoordinates;
private List<ZoneGroupConfiguration> zoneGroups;
private Map<String, ZoneGroupConfiguration> zoneGroups;
private int scheduledUpdateInterval;
private Output output;
@ -49,13 +47,13 @@ public class GeofencingCalculatedFieldConfiguration implements ArgumentsBasedCal
@JsonIgnore
public Map<String, Argument> getArguments() {
Map<String, Argument> args = new HashMap<>(entityCoordinates.toArguments());
zoneGroups.forEach(zg -> args.put(zg.getName(), zg.toArgument()));
zoneGroups.forEach((zgName, zgConfig) -> args.put(zgName, zgConfig.toArgument()));
return args;
}
@Override
public List<EntityId> getReferencedEntities() {
return zoneGroups.stream().map(ZoneGroupConfiguration::getRefEntityId).filter(Objects::nonNull).toList();
return zoneGroups.values().stream().map(ZoneGroupConfiguration::getRefEntityId).filter(Objects::nonNull).toList();
}
@Override
@ -65,7 +63,7 @@ public class GeofencingCalculatedFieldConfiguration implements ArgumentsBasedCal
@Override
public boolean isScheduledUpdateEnabled() {
return scheduledUpdateInterval > 0 && zoneGroups.stream().anyMatch(ZoneGroupConfiguration::hasDynamicSource);
return scheduledUpdateInterval > 0 && zoneGroups.values().stream().anyMatch(ZoneGroupConfiguration::hasDynamicSource);
}
@Override
@ -73,17 +71,11 @@ public class GeofencingCalculatedFieldConfiguration implements ArgumentsBasedCal
if (entityCoordinates == null) {
throw new IllegalArgumentException("Geofencing calculated field entity coordinates must be specified!");
}
entityCoordinates.validate();
if (zoneGroups == null || zoneGroups.isEmpty()) {
throw new IllegalArgumentException("Geofencing calculated field must contain at least one geofencing zone group defined!");
}
entityCoordinates.validate();
Set<String> seen = new HashSet<>();
for (var zg : zoneGroups) {
if (!seen.add(zg.getName())) {
throw new IllegalArgumentException("Geofencing calculated field zone group name must be unique!");
}
zg.validate();
}
zoneGroups.forEach((key, value) -> value.validate(key));
}
}

View File

@ -35,7 +35,6 @@ public class ZoneGroupConfiguration {
private EntityId refEntityId;
private CfArgumentDynamicSourceConfiguration refDynamicSourceConfiguration;
private final String name;
private final String perimeterKeyName;
private final GeofencingReportStrategy reportStrategy;
@ -44,10 +43,7 @@ public class ZoneGroupConfiguration {
private String relationType;
private EntitySearchDirection direction;
public void validate() {
if (StringUtils.isBlank(name)) {
throw new IllegalArgumentException("Zone group name must be specified!");
}
public void validate(String name) {
if (EntityCoordinates.ENTITY_ID_LATITUDE_ARGUMENT_KEY.equals(name) || EntityCoordinates.ENTITY_ID_LONGITUDE_ARGUMENT_KEY.equals(name)) {
throw new IllegalArgumentException("Name '" + name + "' is reserved and cannot be used for zone group!");
}

View File

@ -73,12 +73,12 @@ public class GeofencingCalculatedFieldConfigurationTest {
EntityCoordinates entityCoordinatesMock = mock(EntityCoordinates.class);
cfg.setEntityCoordinates(entityCoordinatesMock);
var zoneGroupConfiguration = mock(ZoneGroupConfiguration.class);
cfg.setZoneGroups(List.of(zoneGroupConfiguration));
cfg.setZoneGroups(Map.of("someGroupName", zoneGroupConfiguration));
cfg.validate();
verify(entityCoordinatesMock).validate();
verify(zoneGroupConfiguration).validate();
verify(zoneGroupConfiguration).validate("someGroupName");
}
@Test
@ -89,38 +89,16 @@ public class GeofencingCalculatedFieldConfigurationTest {
var zoneGroupConfigurationA = mock(ZoneGroupConfiguration.class);
var zoneGroupConfigurationB = mock(ZoneGroupConfiguration.class);
when(zoneGroupConfigurationA.getName()).thenReturn("zoneGroupA");
when(zoneGroupConfigurationB.getName()).thenReturn("zoneGroupB");
String zoneGroupAName = "zoneGroupA";
String zoneGroupBName = "zoneGroupB";
cfg.setZoneGroups(List.of(zoneGroupConfigurationA, zoneGroupConfigurationB));
cfg.setZoneGroups(Map.of("zoneGroupA", zoneGroupConfigurationA, "zoneGroupB", zoneGroupConfigurationB));
assertThatCode(cfg::validate).doesNotThrowAnyException();
verify(entityCoordinatesMock).validate();
verify(zoneGroupConfigurationA).validate();
verify(zoneGroupConfigurationB).validate();
}
@Test
void validateShouldThrowWhenZoneGroupNamesDuplicated() {
var cfg = new GeofencingCalculatedFieldConfiguration();
EntityCoordinates entityCoordinatesMock = mock(EntityCoordinates.class);
cfg.setEntityCoordinates(entityCoordinatesMock);
var zoneGroupConfigurationA = mock(ZoneGroupConfiguration.class);
var zoneGroupConfigurationB = mock(ZoneGroupConfiguration.class);
when(zoneGroupConfigurationA.getName()).thenReturn("zoneGroupDuplicated");
when(zoneGroupConfigurationB.getName()).thenReturn("zoneGroupDuplicated");
cfg.setZoneGroups(List.of(zoneGroupConfigurationA, zoneGroupConfigurationB));
assertThatThrownBy(cfg::validate)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Geofencing calculated field zone group name must be unique!");
verify(entityCoordinatesMock).validate();
verify(zoneGroupConfigurationA).validate();
verify(zoneGroupConfigurationB, never()).validate();
verify(zoneGroupConfigurationA).validate(zoneGroupAName);
verify(zoneGroupConfigurationB).validate(zoneGroupBName);
}
@Test
@ -135,7 +113,7 @@ public class GeofencingCalculatedFieldConfigurationTest {
var cfg = new GeofencingCalculatedFieldConfiguration();
var zoneGroupConfigurationMock = mock(ZoneGroupConfiguration.class);
when(zoneGroupConfigurationMock.hasDynamicSource()).thenReturn(false);
cfg.setZoneGroups(List.of(zoneGroupConfigurationMock));
cfg.setZoneGroups(Map.of("someGroupName", zoneGroupConfigurationMock));
cfg.setScheduledUpdateInterval(60);
assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
}
@ -145,7 +123,7 @@ public class GeofencingCalculatedFieldConfigurationTest {
var cfg = new GeofencingCalculatedFieldConfiguration();
var zoneGroupConfigurationMock = mock(ZoneGroupConfiguration.class);
when(zoneGroupConfigurationMock.hasDynamicSource()).thenReturn(true);
cfg.setZoneGroups(List.of(zoneGroupConfigurationMock));
cfg.setZoneGroups(Map.of("someGroupName", zoneGroupConfigurationMock));
cfg.setScheduledUpdateInterval(60);
assertThat(cfg.isScheduledUpdateEnabled()).isTrue();
}
@ -154,7 +132,7 @@ public class GeofencingCalculatedFieldConfigurationTest {
void testGetArgumentsOverride() {
var cfg = new GeofencingCalculatedFieldConfiguration();
cfg.setEntityCoordinates(new EntityCoordinates(ENTITY_ID_LATITUDE_ARGUMENT_KEY, ENTITY_ID_LONGITUDE_ARGUMENT_KEY));
cfg.setZoneGroups(List.of(new ZoneGroupConfiguration("allowedZones", "perimeter", GeofencingReportStrategy.REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false)));
cfg.setZoneGroups(Map.of("allowedZones", new ZoneGroupConfiguration("perimeter", GeofencingReportStrategy.REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false)));
Map<String, Argument> arguments = cfg.getArguments();

View File

@ -35,21 +35,11 @@ import static org.thingsboard.server.common.data.cf.configuration.geofencing.Geo
public class ZoneGroupConfigurationTest {
@ParameterizedTest
@ValueSource(strings = " ")
@NullAndEmptySource
void validateShouldThrowWhenNameIsNullEmptyOrBlank(String name) {
var zoneGroupConfiguration = new ZoneGroupConfiguration(name, "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatThrownBy(zoneGroupConfiguration::validate)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Zone group name must be specified!");
}
@ParameterizedTest
@ValueSource(strings = {EntityCoordinates.ENTITY_ID_LATITUDE_ARGUMENT_KEY, EntityCoordinates.ENTITY_ID_LONGITUDE_ARGUMENT_KEY})
void validateShouldThrowWhenUsedReservedEntityCoordinateNames(String name) {
var zoneGroupConfiguration = new ZoneGroupConfiguration(name, "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatThrownBy(zoneGroupConfiguration::validate)
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatThrownBy(() -> zoneGroupConfiguration.validate(name))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Name '" + name + "' is reserved and cannot be used for zone group!");
}
@ -58,16 +48,16 @@ public class ZoneGroupConfigurationTest {
@ValueSource(strings = " ")
@NullAndEmptySource
void validateShouldThrowWhenPerimeterKeyNameIsNullEmptyOrBlank(String perimeterKeyName) {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", perimeterKeyName, REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatThrownBy(zoneGroupConfiguration::validate)
var zoneGroupConfiguration = new ZoneGroupConfiguration(perimeterKeyName, REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatThrownBy(() -> zoneGroupConfiguration.validate("allowedZonesGroup"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Perimeter key name must be specified for 'allowedZonesGroup' zone group!");
}
@Test
void validateShouldThrowWhenReportStrategyIsNull() {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", null, false);
assertThatThrownBy(zoneGroupConfiguration::validate)
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", null, false);
assertThatThrownBy(() -> zoneGroupConfiguration.validate("allowedZonesGroup"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Report strategy must be specified for 'allowedZonesGroup' zone group!");
}
@ -76,40 +66,40 @@ public class ZoneGroupConfigurationTest {
@ValueSource(strings = " ")
@NullAndEmptySource
void validateShouldThrowWhenRelationCreationEnabledAndRelationTypeIsNullEmptyOrBlank(String relationType) {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, true);
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, true);
zoneGroupConfiguration.setRelationType(relationType);
assertThatThrownBy(zoneGroupConfiguration::validate)
assertThatThrownBy(() -> zoneGroupConfiguration.validate("allowedZonesGroup"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Relation type must be specified for 'allowedZonesGroup' zone group!");
}
@Test
void validateShouldThrowWhenRelationCreationEnabledAndDirectionIsNull() {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, true);
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, true);
zoneGroupConfiguration.setRelationType(EntityRelation.CONTAINS_TYPE);
zoneGroupConfiguration.setDirection(null);
assertThatThrownBy(zoneGroupConfiguration::validate)
assertThatThrownBy(() -> zoneGroupConfiguration.validate("allowedZonesGroup"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Relation direction must be specified for 'allowedZonesGroup' zone group!");
}
@Test
void validateShouldDoesNotThrowAnyExceptionWhenRelationCreationDisabledAndConfigValid() {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatCode(zoneGroupConfiguration::validate).doesNotThrowAnyException();
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
assertThatCode(() -> zoneGroupConfiguration.validate("allowedZonesGroup")).doesNotThrowAnyException();
}
@Test
void validateShouldDoesNotThrowAnyExceptionWhenRelationCreationEnabledAndConfigValid() {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, true);
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, true);
zoneGroupConfiguration.setRelationType(EntityRelation.CONTAINS_TYPE);
zoneGroupConfiguration.setDirection(EntitySearchDirection.TO);
assertThatCode(zoneGroupConfiguration::validate).doesNotThrowAnyException();
assertThatCode(() -> zoneGroupConfiguration.validate("allowedZonesGroup")).doesNotThrowAnyException();
}
@Test
void whenHasDynamicSourceCalled_shouldReturnTrueIfDynamicSourceConfigurationIsNotNull() {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
zoneGroupConfiguration.setRefDynamicSourceConfiguration(new RelationQueryDynamicSourceConfiguration());
assertThat(zoneGroupConfiguration.hasDynamicSource()).isTrue();
}
@ -124,7 +114,7 @@ public class ZoneGroupConfigurationTest {
@Test
void validateToArgumentsMethodCallWithoutRefEntityId() {
var zoneGroupConfiguration = new ZoneGroupConfiguration("allowedZonesGroup", "perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var zoneGroupConfiguration = new ZoneGroupConfiguration("perimeter", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
Argument zoneGroupArgument = zoneGroupConfiguration.toArgument();
assertThat(zoneGroupArgument).isNotNull();
assertThat(zoneGroupArgument.getRefEntityKey()).isEqualTo(new ReferencedEntityKey("perimeter", ArgumentType.ATTRIBUTE, AttributeScope.SERVER_SCOPE));

View File

@ -44,7 +44,6 @@ import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@ -112,9 +111,9 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
cfg.setEntityCoordinates(entityCoordinates);
// Zone-group argument (ATTRIBUTE) no DYNAMIC configuration, so no scheduling even if the scheduled interval is set
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", "allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
zoneGroupConfiguration.setRefEntityId(device.getId());
cfg.setZoneGroups(List.of(zoneGroupConfiguration));
cfg.setZoneGroups(Map.of("allowed", zoneGroupConfiguration));
// Set a scheduled interval to some value
cfg.setScheduledUpdateInterval(600);
@ -158,13 +157,13 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
cfg.setEntityCoordinates(entityCoordinates);
// Zone-group argument (ATTRIBUTE) make it DYNAMIC so scheduling is enabled
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", "allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var dynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
dynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
dynamicSourceConfiguration.setMaxLevel(1);
dynamicSourceConfiguration.setRelationType(EntityRelation.CONTAINS_TYPE);
zoneGroupConfiguration.setRefDynamicSourceConfiguration(dynamicSourceConfiguration);
cfg.setZoneGroups(List.of(zoneGroupConfiguration));
cfg.setZoneGroups(Map.of("allowed", zoneGroupConfiguration));
// Enable scheduling with an interval below tenant min
cfg.setScheduledUpdateInterval(600);
@ -198,13 +197,13 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
cfg.setEntityCoordinates(entityCoordinates);
// Zone-group argument (ATTRIBUTE) make it DYNAMIC so scheduling is enabled
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", "allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration( "allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var dynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
dynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
dynamicSourceConfiguration.setMaxLevel(Integer.MAX_VALUE);
dynamicSourceConfiguration.setRelationType(EntityRelation.CONTAINS_TYPE);
zoneGroupConfiguration.setRefDynamicSourceConfiguration(dynamicSourceConfiguration);
cfg.setZoneGroups(List.of(zoneGroupConfiguration));
cfg.setZoneGroups(Map.of("allowed", zoneGroupConfiguration));
// Create & save Calculated Field
CalculatedField cf = new CalculatedField();
@ -234,13 +233,13 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
cfg.setEntityCoordinates(entityCoordinates);
// Zone-group argument (ATTRIBUTE) make it DYNAMIC so scheduling is enabled
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration("allowed", "allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration zoneGroupConfiguration = new ZoneGroupConfiguration( "allowed", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var dynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
dynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
dynamicSourceConfiguration.setMaxLevel(1);
dynamicSourceConfiguration.setRelationType(EntityRelation.CONTAINS_TYPE);
zoneGroupConfiguration.setRefDynamicSourceConfiguration(dynamicSourceConfiguration);
cfg.setZoneGroups(List.of(zoneGroupConfiguration));
cfg.setZoneGroups(Map.of("allowed", zoneGroupConfiguration));
// Get tenant profile min.
int min = tbTenantProfileCache.get(tenantId)

View File

@ -54,7 +54,6 @@ import org.thingsboard.server.msa.AbstractContainerTest;
import org.thingsboard.server.msa.ui.utils.EntityPrototypes;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -366,7 +365,7 @@ public class CalculatedFieldTest extends AbstractContainerTest {
cfg.setEntityCoordinates(entityCoordinates);
// Dynamic groups via relations
ZoneGroupConfiguration allowedZoneGroupConfiguration = new ZoneGroupConfiguration("allowedZones", "zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration allowedZoneGroupConfiguration = new ZoneGroupConfiguration("zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var allowedDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
allowedDynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
allowedDynamicSourceConfiguration.setMaxLevel(1);
@ -374,7 +373,7 @@ public class CalculatedFieldTest extends AbstractContainerTest {
allowedDynamicSourceConfiguration.setRelationType("AllowedZone");
allowedZoneGroupConfiguration.setRefDynamicSourceConfiguration(allowedDynamicSourceConfiguration);
ZoneGroupConfiguration restrictedZoneGroupConfiguration = new ZoneGroupConfiguration("restrictedZones", "zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
ZoneGroupConfiguration restrictedZoneGroupConfiguration = new ZoneGroupConfiguration("zone", REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS, false);
var restrictedDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
restrictedDynamicSourceConfiguration.setDirection(EntitySearchDirection.FROM);
restrictedDynamicSourceConfiguration.setMaxLevel(1);
@ -382,7 +381,7 @@ public class CalculatedFieldTest extends AbstractContainerTest {
restrictedDynamicSourceConfiguration.setRelationType("RestrictedZone");
restrictedZoneGroupConfiguration.setRefDynamicSourceConfiguration(restrictedDynamicSourceConfiguration);
cfg.setZoneGroups(List.of(allowedZoneGroupConfiguration, restrictedZoneGroupConfiguration));
cfg.setZoneGroups(Map.of("allowedZones", allowedZoneGroupConfiguration, "restrictedZones", restrictedZoneGroupConfiguration));
Output out = new Output();
out.setType(OutputType.ATTRIBUTES);