Added geofencing CF configuration test
This commit is contained in:
		
							parent
							
								
									4e9b5cf927
								
							
						
					
					
						commit
						d2b9e1066f
					
				@ -135,7 +135,7 @@ public class GeofencingCalculatedFieldState implements CalculatedFieldState {
 | 
			
		||||
            Coordinates entityCoordinates,
 | 
			
		||||
            GeofencingCalculatedFieldConfiguration configuration) {
 | 
			
		||||
 | 
			
		||||
        var geofencingZoneGroupConfigurations = configuration.getGeofencingZoneGroupConfigurations();
 | 
			
		||||
        var geofencingZoneGroupConfigurations = configuration.getZoneGroupConfigurations();
 | 
			
		||||
 | 
			
		||||
        Map<EntityId, GeofencingEvent> zoneEventMap = new HashMap<>();
 | 
			
		||||
        ObjectNode resultNode = JacksonUtil.newObjectNode();
 | 
			
		||||
@ -184,7 +184,7 @@ public class GeofencingCalculatedFieldState implements CalculatedFieldState {
 | 
			
		||||
            Coordinates entityCoordinates,
 | 
			
		||||
            GeofencingCalculatedFieldConfiguration configuration) {
 | 
			
		||||
 | 
			
		||||
        var geofencingZoneGroupConfigurations = configuration.getGeofencingZoneGroupConfigurations();
 | 
			
		||||
        var geofencingZoneGroupConfigurations = configuration.getZoneGroupConfigurations();
 | 
			
		||||
        ObjectNode resultNode = JacksonUtil.newObjectNode();
 | 
			
		||||
 | 
			
		||||
        getGeofencingArguments().forEach((argumentKey, argumentEntry) -> {
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.cf.configuration.Argument;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.ZoneGroupConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.Output;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.OutputType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey;
 | 
			
		||||
@ -701,10 +701,10 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
 | 
			
		||||
        // Zone group reporting config
 | 
			
		||||
        List<GeofencingEvent> reportEvents = Arrays.stream(GeofencingEvent.values()).toList();
 | 
			
		||||
 | 
			
		||||
        GeofencingZoneGroupConfiguration allowedCfg = new GeofencingZoneGroupConfiguration("allowedZone", reportEvents);
 | 
			
		||||
        GeofencingZoneGroupConfiguration restrictedCfg = new GeofencingZoneGroupConfiguration("restrictedZone", reportEvents);
 | 
			
		||||
        ZoneGroupConfiguration allowedCfg = new ZoneGroupConfiguration("allowedZone", reportEvents);
 | 
			
		||||
        ZoneGroupConfiguration restrictedCfg = new ZoneGroupConfiguration("restrictedZone", reportEvents);
 | 
			
		||||
 | 
			
		||||
        cfg.setGeofencingZoneGroupConfigurations(Map.of(
 | 
			
		||||
        cfg.setZoneGroupConfigurations(Map.of(
 | 
			
		||||
                "allowedZones", allowedCfg,
 | 
			
		||||
                "restrictedZones", restrictedCfg
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.CalculatedFieldConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.ZoneGroupConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.Output;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.OutputType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey;
 | 
			
		||||
@ -337,9 +337,9 @@ public class GeofencingCalculatedFieldStateTest {
 | 
			
		||||
        config.setArguments(Map.of("latitude", argument1, "longitude", argument2, "allowedZones", argument3, "restrictedZones", argument4));
 | 
			
		||||
 | 
			
		||||
        List<GeofencingEvent> reportEvents = Arrays.stream(GeofencingEvent.values()).toList();
 | 
			
		||||
        GeofencingZoneGroupConfiguration allowedZoneGroupConfiguration = new GeofencingZoneGroupConfiguration("allowedZone", reportEvents);
 | 
			
		||||
        GeofencingZoneGroupConfiguration restrictedZoneGroupConfiguration = new GeofencingZoneGroupConfiguration("restrictedZone", reportEvents);
 | 
			
		||||
        config.setGeofencingZoneGroupConfigurations(Map.of("allowedZones", allowedZoneGroupConfiguration, "restrictedZones", restrictedZoneGroupConfiguration));
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneGroupConfiguration = new ZoneGroupConfiguration("allowedZone", reportEvents);
 | 
			
		||||
        ZoneGroupConfiguration restrictedZoneGroupConfiguration = new ZoneGroupConfiguration("restrictedZone", reportEvents);
 | 
			
		||||
        config.setZoneGroupConfigurations(Map.of("allowedZones", allowedZoneGroupConfiguration, "restrictedZones", restrictedZoneGroupConfiguration));
 | 
			
		||||
 | 
			
		||||
        config.setCreateRelationsWithMatchedZones(true);
 | 
			
		||||
        config.setZoneRelationType("CurrentZone");
 | 
			
		||||
 | 
			
		||||
@ -30,14 +30,14 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
public class GeofencingZoneStateTest {
 | 
			
		||||
 | 
			
		||||
    private final AssetId ZONE_ID = new AssetId(UUID.fromString("628730fd-d625-417f-9c6d-ae9fe4addbdb"));
 | 
			
		||||
    private final String POLYGON = """
 | 
			
		||||
                {"type":"POLYGON","polygonsDefinition":"[[50.472000, 30.504000], [50.472000, 30.506000], [50.474000, 30.506000], [50.474000, 30.504000]]"}
 | 
			
		||||
                """;
 | 
			
		||||
 | 
			
		||||
    private GeofencingZoneState state;
 | 
			
		||||
 | 
			
		||||
    @BeforeEach
 | 
			
		||||
    void setUp() {
 | 
			
		||||
        String POLYGON = """
 | 
			
		||||
                {"type":"POLYGON","polygonsDefinition":"[[50.472000, 30.504000], [50.472000, 30.506000], [50.474000, 30.506000], [50.474000, 30.504000]]"}
 | 
			
		||||
                """;
 | 
			
		||||
        state = new GeofencingZoneState(ZONE_ID, new BaseAttributeKvEntry(new JsonDataEntry("zone", POLYGON), 100L, 1L));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
 | 
			
		||||
    private boolean createRelationsWithMatchedZones;
 | 
			
		||||
    private String zoneRelationType;
 | 
			
		||||
    private EntitySearchDirection zoneRelationDirection;
 | 
			
		||||
    private Map<String, GeofencingZoneGroupConfiguration> geofencingZoneGroupConfigurations;
 | 
			
		||||
    private Map<String, ZoneGroupConfiguration> zoneGroupConfigurations;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CalculatedFieldType getType() {
 | 
			
		||||
@ -60,13 +60,9 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
 | 
			
		||||
    @Override
 | 
			
		||||
    public void validate() {
 | 
			
		||||
        if (arguments == null) {
 | 
			
		||||
            throw new IllegalArgumentException("Geofencing calculated field arguments are empty!");
 | 
			
		||||
        }
 | 
			
		||||
        if (arguments.size() < 3) {
 | 
			
		||||
            throw new IllegalArgumentException("Geofencing calculated field must contain at least 3 arguments!");
 | 
			
		||||
            throw new IllegalArgumentException("Geofencing calculated field arguments must be specified!");
 | 
			
		||||
        }
 | 
			
		||||
        validateCoordinateArguments();
 | 
			
		||||
 | 
			
		||||
        Map<String, Argument> zoneGroupsArguments = getZoneGroupArguments();
 | 
			
		||||
        if (zoneGroupsArguments.isEmpty()) {
 | 
			
		||||
            throw new IllegalArgumentException("Geofencing calculated field must contain at least one geofencing zone group defined!");
 | 
			
		||||
@ -81,32 +77,30 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (StringUtils.isBlank(zoneRelationType)) {
 | 
			
		||||
            throw new IllegalArgumentException("Zone relation type must be specified when to maintain relations with matched zones!");
 | 
			
		||||
            throw new IllegalArgumentException("Zone relation type must be specified to create relations with matched zones!");
 | 
			
		||||
        }
 | 
			
		||||
        if (zoneRelationDirection == null) {
 | 
			
		||||
            throw new IllegalArgumentException("Zone relation direction must be specified to maintain relations with matched zones!");
 | 
			
		||||
            throw new IllegalArgumentException("Zone relation direction must be specified to create relations with matched zones!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateZoneGroupConfigurations(Map<String, Argument> zoneGroupsArguments) {
 | 
			
		||||
        if (geofencingZoneGroupConfigurations == null) {
 | 
			
		||||
            throw new IllegalArgumentException("Geofencing calculated field zone group configurations are empty!");
 | 
			
		||||
        if (zoneGroupConfigurations == null || zoneGroupConfigurations.isEmpty()) {
 | 
			
		||||
            throw new IllegalArgumentException("Zone groups configuration should be specified!");
 | 
			
		||||
        }
 | 
			
		||||
        Set<String> usedPrefixes = new HashSet<>();
 | 
			
		||||
        geofencingZoneGroupConfigurations.forEach((zoneGroupName, config) -> {
 | 
			
		||||
            Argument zoneGroupArgument = zoneGroupsArguments.get(zoneGroupName);
 | 
			
		||||
            if (zoneGroupArgument == null) {
 | 
			
		||||
                throw new IllegalArgumentException("Geofencing calculated field zone group configuration is not configured for zone group: " + zoneGroupName);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        zoneGroupsArguments.forEach((zoneGroupName, zoneGroupArgument) -> {
 | 
			
		||||
            ZoneGroupConfiguration config = zoneGroupConfigurations.get(zoneGroupName);
 | 
			
		||||
            if (config == null) {
 | 
			
		||||
                throw new IllegalArgumentException("Zone group configuration is not configured for zone group: " + zoneGroupName);
 | 
			
		||||
                throw new IllegalArgumentException("Zone group configuration is not configured for '" + zoneGroupName + "' argument!");
 | 
			
		||||
            }
 | 
			
		||||
            if (CollectionsUtil.isEmpty(config.getReportEvents())) {
 | 
			
		||||
                throw new IllegalArgumentException("Zone group configuration report events must be specified for zone group: " + zoneGroupName);
 | 
			
		||||
                throw new IllegalArgumentException("Zone group configuration report events must be specified for '" + zoneGroupName + "' argument!");
 | 
			
		||||
            }
 | 
			
		||||
            String prefix = config.getReportTelemetryPrefix();
 | 
			
		||||
            if (StringUtils.isBlank(prefix)) {
 | 
			
		||||
                throw new IllegalArgumentException("Report telemetry prefix should be specified for zone group: " + zoneGroupName);
 | 
			
		||||
                throw new IllegalArgumentException("Report telemetry prefix should be specified for '" + zoneGroupName + "' argument!");
 | 
			
		||||
            }
 | 
			
		||||
            if (!usedPrefixes.add(prefix)) {
 | 
			
		||||
                throw new IllegalArgumentException("Duplicate report telemetry prefix found: '" + prefix + "'. Must be unique!");
 | 
			
		||||
@ -118,26 +112,23 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
 | 
			
		||||
        for (String coordinateKey : coordinateKeys) {
 | 
			
		||||
            Argument argument = arguments.get(coordinateKey);
 | 
			
		||||
            if (argument == null) {
 | 
			
		||||
                throw new IllegalArgumentException("Missing required coordinates argument: " + coordinateKey);
 | 
			
		||||
                throw new IllegalArgumentException("Missing required coordinates argument: " + coordinateKey + "!");
 | 
			
		||||
            }
 | 
			
		||||
            ReferencedEntityKey refEntityKey = validateAndGetRefEntityKey(argument, coordinateKey);
 | 
			
		||||
            if (!ArgumentType.TS_LATEST.equals(refEntityKey.getType())) {
 | 
			
		||||
                throw new IllegalArgumentException("Argument '" + coordinateKey + "' must be of type TS_LATEST.");
 | 
			
		||||
                throw new IllegalArgumentException("Argument '" + coordinateKey + "' must be of type TS_LATEST!");
 | 
			
		||||
            }
 | 
			
		||||
            if (argument.hasDynamicSource()) {
 | 
			
		||||
                throw new IllegalArgumentException("Dynamic source is not allowed for argument: '" + coordinateKey + "'.");
 | 
			
		||||
                throw new IllegalArgumentException("Dynamic source is not allowed for '" + coordinateKey + "' argument!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateZoneGroupAruguments(Map<String, Argument> zoneGroupsArguments) {
 | 
			
		||||
        zoneGroupsArguments.forEach((argumentKey, argument) -> {
 | 
			
		||||
            if (argument == null) {
 | 
			
		||||
                throw new IllegalArgumentException("Zone group argument is not configured: " + argumentKey);
 | 
			
		||||
            }
 | 
			
		||||
            ReferencedEntityKey refEntityKey = validateAndGetRefEntityKey(argument, argumentKey);
 | 
			
		||||
            if (!ArgumentType.ATTRIBUTE.equals(refEntityKey.getType())) {
 | 
			
		||||
                throw new IllegalArgumentException("Argument '" + argumentKey + "' must be of type ATTRIBUTE.");
 | 
			
		||||
                throw new IllegalArgumentException("Argument '" + argumentKey + "' must be of type ATTRIBUTE!");
 | 
			
		||||
            }
 | 
			
		||||
            if (argument.hasDynamicSource()) {
 | 
			
		||||
                argument.getRefDynamicSourceConfiguration().validate();
 | 
			
		||||
@ -148,6 +139,7 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
 | 
			
		||||
    private Map<String, Argument> getZoneGroupArguments() {
 | 
			
		||||
        return arguments.entrySet()
 | 
			
		||||
                .stream()
 | 
			
		||||
                .filter(entry -> entry.getValue() != null)
 | 
			
		||||
                .filter(entry -> !coordinateKeys.contains(entry.getKey()))
 | 
			
		||||
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@ import lombok.Data;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class GeofencingZoneGroupConfiguration {
 | 
			
		||||
public class ZoneGroupConfiguration {
 | 
			
		||||
 | 
			
		||||
    private final String reportTelemetryPrefix;
 | 
			
		||||
    private final List<GeofencingEvent> reportEvents;
 | 
			
		||||
@ -0,0 +1,472 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2025 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.common.data.cf.configuration;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.junit.jupiter.api.extension.ExtendWith;
 | 
			
		||||
import org.junit.jupiter.params.ParameterizedTest;
 | 
			
		||||
import org.junit.jupiter.params.provider.NullAndEmptySource;
 | 
			
		||||
import org.junit.jupiter.params.provider.ValueSource;
 | 
			
		||||
import org.mockito.junit.jupiter.MockitoExtension;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
import static org.mockito.Mockito.verify;
 | 
			
		||||
import static org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration.ENTITY_ID_LATITUDE_ARGUMENT_KEY;
 | 
			
		||||
import static org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration.ENTITY_ID_LONGITUDE_ARGUMENT_KEY;
 | 
			
		||||
 | 
			
		||||
@ExtendWith(MockitoExtension.class)
 | 
			
		||||
public class GeofencingCalculatedFieldConfigurationTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void typeShouldBeGeofencing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        assertThat(cfg.getType()).isEqualTo(CalculatedFieldType.GEOFENCING);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenArgumentsNull() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(null);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Geofencing calculated field arguments must be specified!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLatitudeArgIsMissing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, null);
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Missing required coordinates argument: " + ENTITY_ID_LATITUDE_ARGUMENT_KEY + "!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLongitudeArgIsMissing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, null);
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Missing required coordinates argument: " + ENTITY_ID_LONGITUDE_ARGUMENT_KEY + "!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLatitudeReferenceKeyIsNull() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument(null),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST))
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LATITUDE_ARGUMENT_KEY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLongitudeReferenceKeyIsNull() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument(null))
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LONGITUDE_ARGUMENT_KEY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLatitudeReferenceKeyTypeIsNull() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument(new ReferencedEntityKey("latitude", null, null)),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST))
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LATITUDE_ARGUMENT_KEY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenReferenceKeyTypeIsNull() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument(new ReferencedEntityKey("longitude", null, null)))
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LONGITUDE_ARGUMENT_KEY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLatitudeArgHasWrongArgumentType() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.ATTRIBUTE),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST)
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Argument '" + ENTITY_ID_LATITUDE_ARGUMENT_KEY + "' must be of type TS_LATEST!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLongitudeArgHasWrongArgumentType() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.ATTRIBUTE)
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Argument '" + ENTITY_ID_LONGITUDE_ARGUMENT_KEY + "' must be of type TS_LATEST!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLatitudeArgHasDynamicSource() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
 | 
			
		||||
        Argument latitudeArg = toArgument("latitude", ArgumentType.TS_LATEST);
 | 
			
		||||
        var refDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
 | 
			
		||||
        latitudeArg.setRefDynamicSourceConfiguration(refDynamicSourceConfiguration);
 | 
			
		||||
 | 
			
		||||
        Argument longitudeArg = toArgument("longitude", ArgumentType.TS_LATEST);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(Map.of(ENTITY_ID_LATITUDE_ARGUMENT_KEY, latitudeArg, ENTITY_ID_LONGITUDE_ARGUMENT_KEY, longitudeArg));
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Dynamic source is not allowed for '" + ENTITY_ID_LATITUDE_ARGUMENT_KEY + "' argument!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenLongitudeArgHasDynamicSource() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
 | 
			
		||||
        Argument latitudeArg = toArgument("latitude", ArgumentType.TS_LATEST);
 | 
			
		||||
        Argument longitudeArg = toArgument("longitude", ArgumentType.TS_LATEST);
 | 
			
		||||
        var refDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
 | 
			
		||||
        longitudeArg.setRefDynamicSourceConfiguration(refDynamicSourceConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(Map.of(ENTITY_ID_LATITUDE_ARGUMENT_KEY, latitudeArg, ENTITY_ID_LONGITUDE_ARGUMENT_KEY, longitudeArg));
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Dynamic source is not allowed for '" + ENTITY_ID_LONGITUDE_ARGUMENT_KEY + "' argument!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenGeofencingArgumentsMissing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(
 | 
			
		||||
                ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
 | 
			
		||||
                ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST)
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Geofencing calculated field must contain at least one geofencing zone group defined!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenZoneGroupArgumentIsNull() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put("someZones", null);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Geofencing calculated field must contain at least one geofencing zone group defined!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenZoneGroupArgumentHasInvalidArgumentType() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put("allowedZones", toArgument("allowedZone", ArgumentType.TS_LATEST));
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Argument 'allowedZones' must be of type ATTRIBUTE!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldCallDynamicSourceConfigValidationWhenZoneGroupArgumentHasDynamicSourceConfiguration() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
 | 
			
		||||
        cfg.validate();
 | 
			
		||||
 | 
			
		||||
        verify(refDynamicSourceConfigurationMock).validate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenZoneGroupConfigurationIsMissing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(null);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(false);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Zone groups configuration should be specified!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenReportTelemetryPrefixDuplicate() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        Argument restrictedZonesArg = toArgument("restrictedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
        arguments.put("restrictedZones", restrictedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("theSamePrefixTest", Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        ZoneGroupConfiguration restrictedZoneConfiguration = new ZoneGroupConfiguration("theSamePrefixTest", Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration, "restrictedZones", restrictedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(false);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Duplicate report telemetry prefix found: 'theSamePrefixTest'. Must be unique!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenZoneGroupArgumentConfigurationIsMissing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("someOtherZones", allowedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(false);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Zone group configuration is not configured for 'allowedZones' argument!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenZoneGroupConfigurationReportEventsAreNotSpecified() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", null);
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(false);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Zone group configuration report events must be specified for 'allowedZones' argument!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ParameterizedTest
 | 
			
		||||
    @NullAndEmptySource
 | 
			
		||||
    @ValueSource(strings = "  ")
 | 
			
		||||
    void validateShouldThrowWhenZoneGroupConfigurationTelemetryPrefixIsBlankOrNull(String reportTelemetryPrefix) {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration(reportTelemetryPrefix, Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(false);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Report telemetry prefix should be specified for 'allowedZones' argument!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ParameterizedTest
 | 
			
		||||
    @NullAndEmptySource
 | 
			
		||||
    @ValueSource(strings = "  ")
 | 
			
		||||
    void validateShouldThrowWhenHasBlankOrNullZoneRelationType(String zoneRelationType) {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(true);
 | 
			
		||||
        cfg.setZoneRelationType(zoneRelationType);
 | 
			
		||||
        cfg.setZoneRelationDirection(EntitySearchDirection.TO);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Zone relation type must be specified to create relations with matched zones!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void validateShouldThrowWhenNoZoneRelationDirectionSpecified() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        var arguments = new HashMap<String, Argument>();
 | 
			
		||||
        arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
 | 
			
		||||
        Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
 | 
			
		||||
        allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
 | 
			
		||||
        arguments.put("allowedZones", allowedZonesArg);
 | 
			
		||||
 | 
			
		||||
        ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
 | 
			
		||||
        Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
 | 
			
		||||
 | 
			
		||||
        cfg.setArguments(arguments);
 | 
			
		||||
        cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
 | 
			
		||||
        cfg.setCreateRelationsWithMatchedZones(true);
 | 
			
		||||
        cfg.setZoneRelationType("SomeRelationType");
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(cfg::validate)
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Zone relation direction must be specified to create relations with matched zones!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void scheduledUpdateDisabledWhenIntervalIsZero() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setScheduledUpdateIntervalSec(0);
 | 
			
		||||
        assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void scheduledUpdateDisabledWhenIntervalIsGreaterThanZeroButArgumentsAreEmpty() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of());
 | 
			
		||||
        cfg.setScheduledUpdateIntervalSec(60);
 | 
			
		||||
        assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void scheduledUpdateDisabledWhenIntervalIsGreaterThanZeroButDynamicArgumentsAreMissing() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        cfg.setArguments(Map.of(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST)));
 | 
			
		||||
        cfg.setScheduledUpdateIntervalSec(60);
 | 
			
		||||
        assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void scheduledUpdateEnabledWhenIntervalIsGreaterThanZeroAndDynamicArgumentsPresent() {
 | 
			
		||||
        var cfg = new GeofencingCalculatedFieldConfiguration();
 | 
			
		||||
        Argument someDynamicArgument = toArgument("someDynamicArgument", ArgumentType.ATTRIBUTE);
 | 
			
		||||
        someDynamicArgument.setRefDynamicSourceConfiguration(new RelationQueryDynamicSourceConfiguration());
 | 
			
		||||
        cfg.setArguments(Map.of("someDynamicArugument", someDynamicArgument));
 | 
			
		||||
        cfg.setScheduledUpdateIntervalSec(60);
 | 
			
		||||
        assertThat(cfg.isScheduledUpdateEnabled()).isTrue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private Argument toArgument(String key, ArgumentType type) {
 | 
			
		||||
        var referencedEntityKey = new ReferencedEntityKey(key, type, null);
 | 
			
		||||
        return toArgument(referencedEntityKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Argument toArgument(ReferencedEntityKey referencedEntityKey) {
 | 
			
		||||
        Argument argument = new Argument();
 | 
			
		||||
        argument.setRefEntityKey(referencedEntityKey);
 | 
			
		||||
        return argument;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user