added tbCalculatedField Service
This commit is contained in:
		
							parent
							
								
									4dbc35273a
								
							
						
					
					
						commit
						bcef71f78d
					
				@ -27,23 +27,14 @@ import org.springframework.web.bind.annotation.RequestMethod;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseStatus;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedField;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedFieldConfig;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CalculatedFieldId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.config.annotations.ApiOperation;
 | 
			
		||||
import org.thingsboard.server.dao.cf.CalculatedFieldService;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.entitiy.cf.TbCalculatedFieldService;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
 | 
			
		||||
import java.util.EnumSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
 | 
			
		||||
 | 
			
		||||
@ -54,10 +45,7 @@ import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LI
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class CalculatedFieldController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private static final Set<EntityType> supportedEntityTypesForReferencedEntities = EnumSet.of(
 | 
			
		||||
            EntityType.TENANT, EntityType.CUSTOMER, EntityType.ASSET, EntityType.DEVICE);
 | 
			
		||||
 | 
			
		||||
    private final CalculatedFieldService calculatedFieldService;
 | 
			
		||||
    private final TbCalculatedFieldService tbCalculatedFieldService;
 | 
			
		||||
 | 
			
		||||
    public static final String CALCULATED_FIELD_ID = "calculatedFieldId";
 | 
			
		||||
 | 
			
		||||
@ -75,8 +63,7 @@ public class CalculatedFieldController extends BaseController {
 | 
			
		||||
                                               @RequestBody CalculatedField calculatedField) throws Exception {
 | 
			
		||||
        calculatedField.setTenantId(getTenantId());
 | 
			
		||||
        checkEntityId(calculatedField.getEntityId(), Operation.WRITE_CALCULATED_FIELD);
 | 
			
		||||
        checkReferencedEntities(calculatedField.getConfiguration());
 | 
			
		||||
        return calculatedFieldService.save(calculatedField);
 | 
			
		||||
        return tbCalculatedFieldService.save(calculatedField, getCurrentUser());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get Calculated Field (getCalculatedFieldById)",
 | 
			
		||||
@ -88,7 +75,7 @@ public class CalculatedFieldController extends BaseController {
 | 
			
		||||
    public CalculatedField getCalculatedFieldById(@Parameter @PathVariable(CALCULATED_FIELD_ID) String strCalculatedFieldId) throws ThingsboardException {
 | 
			
		||||
        checkParameter(CALCULATED_FIELD_ID, strCalculatedFieldId);
 | 
			
		||||
        CalculatedFieldId calculatedFieldId = new CalculatedFieldId(toUUID(strCalculatedFieldId));
 | 
			
		||||
        CalculatedField calculatedField = calculatedFieldService.findById(getTenantId(), calculatedFieldId);
 | 
			
		||||
        CalculatedField calculatedField = tbCalculatedFieldService.findById(calculatedFieldId, getCurrentUser());
 | 
			
		||||
        checkNotNull(calculatedField);
 | 
			
		||||
        checkEntityId(calculatedField.getEntityId(), Operation.READ_CALCULATED_FIELD);
 | 
			
		||||
        return calculatedField;
 | 
			
		||||
@ -103,23 +90,9 @@ public class CalculatedFieldController extends BaseController {
 | 
			
		||||
    public void deleteCalculatedField(@PathVariable(CALCULATED_FIELD_ID) String strCalculatedField) throws Exception {
 | 
			
		||||
        checkParameter(CALCULATED_FIELD_ID, strCalculatedField);
 | 
			
		||||
        CalculatedFieldId calculatedFieldId = new CalculatedFieldId(toUUID(strCalculatedField));
 | 
			
		||||
        TenantId tenantId = getTenantId();
 | 
			
		||||
        CalculatedField calculatedField = calculatedFieldService.findById(tenantId, calculatedFieldId);
 | 
			
		||||
        CalculatedField calculatedField = tbCalculatedFieldService.findById(calculatedFieldId, getCurrentUser());
 | 
			
		||||
        checkEntityId(calculatedField.getEntityId(), Operation.WRITE_CALCULATED_FIELD);
 | 
			
		||||
        calculatedFieldService.deleteCalculatedField(getTenantId(), calculatedFieldId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkReferencedEntities(CalculatedFieldConfig calculatedFieldConfig) throws ThingsboardException {
 | 
			
		||||
        List<EntityId> referencedEntityIds = calculatedFieldConfig.getArguments().values().stream()
 | 
			
		||||
                .map(CalculatedFieldConfig.Argument::getEntityId)
 | 
			
		||||
                .filter(Objects::nonNull)
 | 
			
		||||
                .toList();
 | 
			
		||||
        for (EntityId referencedEntityId : referencedEntityIds) {
 | 
			
		||||
            if (!supportedEntityTypesForReferencedEntities.contains(referencedEntityId.getEntityType())) {
 | 
			
		||||
                throw new IllegalArgumentException("Calculated fields do not support entity type '" + referencedEntityId.getEntityType() + "' for referenced entities.");
 | 
			
		||||
            }
 | 
			
		||||
            checkEntityId(referencedEntityId, Operation.READ);
 | 
			
		||||
        }
 | 
			
		||||
        tbCalculatedFieldService.delete(calculatedField, getCurrentUser());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -25,16 +25,30 @@ import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.core.env.Environment;
 | 
			
		||||
import org.thingsboard.server.cluster.TbClusterService;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.HasTenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
			
		||||
import org.thingsboard.server.common.data.id.HasId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UUIDBased;
 | 
			
		||||
import org.thingsboard.server.common.data.util.ThrowingBiFunction;
 | 
			
		||||
import org.thingsboard.server.dao.alarm.AlarmService;
 | 
			
		||||
import org.thingsboard.server.dao.asset.AssetProfileService;
 | 
			
		||||
import org.thingsboard.server.dao.asset.AssetService;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceProfileService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.edge.EdgeService;
 | 
			
		||||
import org.thingsboard.server.dao.model.ModelConstants;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantService;
 | 
			
		||||
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.AccessControlService;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Resource;
 | 
			
		||||
import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService;
 | 
			
		||||
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
 | 
			
		||||
 | 
			
		||||
@ -43,6 +57,8 @@ import java.util.Optional;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateId;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public abstract class AbstractTbEntityService {
 | 
			
		||||
 | 
			
		||||
@ -71,6 +87,18 @@ public abstract class AbstractTbEntityService {
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
    @Lazy
 | 
			
		||||
    private EntitiesVersionControlService vcService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected AccessControlService accessControlService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected TenantService tenantService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected AssetService assetService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected DeviceService deviceService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected AssetProfileService assetProfileService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected DeviceProfileService deviceProfileService;
 | 
			
		||||
 | 
			
		||||
    protected boolean isTestProfile() {
 | 
			
		||||
        return Set.of(this.env.getActiveProfiles()).contains("test");
 | 
			
		||||
@ -120,4 +148,23 @@ public abstract class AbstractTbEntityService {
 | 
			
		||||
            return Futures.immediateFailedFuture(new RuntimeException("Operation not supported!"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected <E extends HasId<I> & HasTenantId, I extends EntityId> E checkEntityId(I entityId, ThrowingBiFunction<TenantId, I, E> findingFunction, Operation operation, SecurityUser user) throws Exception {
 | 
			
		||||
        try {
 | 
			
		||||
            validateId((UUIDBased) entityId, "Invalid entity id");
 | 
			
		||||
            E entity = findingFunction.apply(user.getTenantId(), entityId);
 | 
			
		||||
            checkNotNull(entity, entityId.getEntityType().getNormalName() + " with id [" + entityId + "] is not found");
 | 
			
		||||
            return checkEntity(user, entity, operation);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected <E extends HasId<I> & HasTenantId, I extends EntityId> E checkEntity(SecurityUser user, E entity, Operation operation) throws ThingsboardException {
 | 
			
		||||
        checkNotNull(entity, "Entity not found");
 | 
			
		||||
        accessControlService.checkPermission(user, Resource.of(entity.getId().getEntityType()), operation, entity.getId(), entity);
 | 
			
		||||
        return entity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,149 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2024 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.service.entitiy.cf;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.HasTenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedField;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedFieldConfig;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedFieldLink;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.AssetId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.AssetProfileId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CalculatedFieldId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CalculatedFieldLinkId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.HasId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.dao.cf.CalculatedFieldService;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateEntityId;
 | 
			
		||||
 | 
			
		||||
@TbCoreComponent
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class DefaultTbCalculatedFieldService extends AbstractTbEntityService implements TbCalculatedFieldService {
 | 
			
		||||
 | 
			
		||||
    private final Map<CalculatedFieldId, CalculatedField> calculatedFields;
 | 
			
		||||
    private final Map<CalculatedFieldLinkId, CalculatedFieldLink> calculatedFieldLinks;
 | 
			
		||||
    private final CalculatedFieldService calculatedFieldService;
 | 
			
		||||
 | 
			
		||||
    public DefaultTbCalculatedFieldService(CalculatedFieldService calculatedFieldService) {
 | 
			
		||||
        this.calculatedFields = calculatedFieldService.findAll().stream().collect(Collectors.toMap(CalculatedField::getId, cf -> cf));
 | 
			
		||||
        this.calculatedFieldLinks = calculatedFieldService.findAllCalculatedFieldLinks().stream().collect(Collectors.toMap(CalculatedFieldLink::getId, cfl -> cfl));
 | 
			
		||||
        this.calculatedFieldService = calculatedFieldService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onMsg() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CalculatedField save(CalculatedField calculatedField, SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        ActionType actionType = calculatedField.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
 | 
			
		||||
        TenantId tenantId = calculatedField.getTenantId();
 | 
			
		||||
        try {
 | 
			
		||||
            checkEntityExistence(tenantId, calculatedField.getEntityId());
 | 
			
		||||
            checkReferencedEntities(calculatedField.getConfiguration(), user);
 | 
			
		||||
            CalculatedField savedCalculatedField = checkNotNull(calculatedFieldService.save(calculatedField));
 | 
			
		||||
            logEntityActionService.logEntityAction(tenantId, savedCalculatedField.getId(), savedCalculatedField, actionType, user);
 | 
			
		||||
            return savedCalculatedField;
 | 
			
		||||
        } catch (ThingsboardException e) {
 | 
			
		||||
            logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.CALCULATED_FIELD), calculatedField, actionType, user, e);
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CalculatedField findById(CalculatedFieldId calculatedFieldId, SecurityUser user) {
 | 
			
		||||
        return calculatedFieldService.findById(user.getTenantId(), calculatedFieldId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public void delete(CalculatedField calculatedField, SecurityUser user) {
 | 
			
		||||
        ActionType actionType = ActionType.DELETED;
 | 
			
		||||
        TenantId tenantId = calculatedField.getTenantId();
 | 
			
		||||
        CalculatedFieldId calculatedFieldId = calculatedField.getId();
 | 
			
		||||
        try {
 | 
			
		||||
            calculatedFieldService.deleteCalculatedField(tenantId, calculatedFieldId);
 | 
			
		||||
            logEntityActionService.logEntityAction(tenantId, calculatedFieldId, calculatedField, actionType, user, calculatedFieldId.toString());
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.CALCULATED_FIELD), actionType, user, e, calculatedFieldId.toString());
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkEntityExistence(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
        switch (entityId.getEntityType()) {
 | 
			
		||||
            case ASSET -> Optional.ofNullable(assetService.findAssetById(tenantId, (AssetId) entityId))
 | 
			
		||||
                    .orElseThrow(() -> new IllegalArgumentException("Asset with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            case DEVICE -> Optional.ofNullable(deviceService.findDeviceById(tenantId, (DeviceId) entityId))
 | 
			
		||||
                    .orElseThrow(() -> new IllegalArgumentException("Device with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            case ASSET_PROFILE ->
 | 
			
		||||
                    Optional.ofNullable(assetProfileService.findAssetProfileById(tenantId, (AssetProfileId) entityId))
 | 
			
		||||
                            .orElseThrow(() -> new IllegalArgumentException("Asset Profile with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            case DEVICE_PROFILE ->
 | 
			
		||||
                    Optional.ofNullable(deviceProfileService.findDeviceProfileById(tenantId, (DeviceProfileId) entityId))
 | 
			
		||||
                            .orElseThrow(() -> new IllegalArgumentException("Device Profile with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            default ->
 | 
			
		||||
                    throw new IllegalArgumentException("Entity type '" + entityId.getEntityType() + "' does not support calculated fields.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <E extends HasId<I> & HasTenantId, I extends EntityId> void checkReferencedEntities(CalculatedFieldConfig calculatedFieldConfig, SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        List<EntityId> referencedEntityIds = calculatedFieldConfig.getArguments().values().stream()
 | 
			
		||||
                .map(CalculatedFieldConfig.Argument::getEntityId)
 | 
			
		||||
                .filter(Objects::nonNull)
 | 
			
		||||
                .toList();
 | 
			
		||||
        for (EntityId referencedEntityId : referencedEntityIds) {
 | 
			
		||||
            validateEntityId(referencedEntityId, id -> "Invalid entity id " + id);
 | 
			
		||||
            E entity = findEntity(user.getTenantId(), referencedEntityId);
 | 
			
		||||
            checkNotNull(entity);
 | 
			
		||||
            checkEntity(user, entity, Operation.READ);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <E extends HasId<I> & HasTenantId, I extends EntityId> E findEntity(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
        return (E) switch (entityId.getEntityType()) {
 | 
			
		||||
            case TENANT -> tenantService.findTenantById((TenantId) entityId);
 | 
			
		||||
            case CUSTOMER -> customerService.findCustomerById(tenantId, (CustomerId) entityId);
 | 
			
		||||
            case ASSET -> assetService.findAssetById(tenantId, (AssetId) entityId);
 | 
			
		||||
            case DEVICE -> deviceService.findDeviceById(tenantId, (DeviceId) entityId);
 | 
			
		||||
            default -> throw new IllegalArgumentException("Calculated fields do not support entity type '" + entityId.getEntityType() + "' for referenced entities.");
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2024 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.service.entitiy.cf;
 | 
			
		||||
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedField;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CalculatedFieldId;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
 | 
			
		||||
public interface TbCalculatedFieldService {
 | 
			
		||||
 | 
			
		||||
    void onMsg();
 | 
			
		||||
 | 
			
		||||
    CalculatedField save(CalculatedField calculatedField, SecurityUser user) throws ThingsboardException;
 | 
			
		||||
 | 
			
		||||
    CalculatedField findById(CalculatedFieldId calculatedFieldId, SecurityUser user);
 | 
			
		||||
 | 
			
		||||
    void delete(CalculatedField calculatedField, SecurityUser user);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -23,12 +23,16 @@ import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.dao.entity.EntityDaoService;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public interface CalculatedFieldService extends EntityDaoService {
 | 
			
		||||
 | 
			
		||||
    CalculatedField save(CalculatedField calculatedField);
 | 
			
		||||
 | 
			
		||||
    CalculatedField findById(TenantId tenantId, CalculatedFieldId calculatedFieldId);
 | 
			
		||||
 | 
			
		||||
    List<CalculatedField> findAll();
 | 
			
		||||
 | 
			
		||||
    void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId);
 | 
			
		||||
 | 
			
		||||
    int deleteAllCalculatedFieldsByEntityId(TenantId tenantId, EntityId entityId);
 | 
			
		||||
@ -37,6 +41,8 @@ public interface CalculatedFieldService extends EntityDaoService {
 | 
			
		||||
 | 
			
		||||
    CalculatedFieldLink findCalculatedFieldLinkById(TenantId tenantId, CalculatedFieldLinkId calculatedFieldLinkId);
 | 
			
		||||
 | 
			
		||||
    List<CalculatedFieldLink> findAllCalculatedFieldLinks();
 | 
			
		||||
 | 
			
		||||
    boolean existsByEntityId(TenantId tenantId, EntityId entityId);
 | 
			
		||||
 | 
			
		||||
    boolean referencedInAnyCalculatedField(TenantId tenantId, EntityId referencedEntityId);
 | 
			
		||||
 | 
			
		||||
@ -22,19 +22,11 @@ import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedField;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedFieldConfig;
 | 
			
		||||
import org.thingsboard.server.common.data.cf.CalculatedFieldLink;
 | 
			
		||||
import org.thingsboard.server.common.data.id.AssetId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.AssetProfileId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CalculatedFieldId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CalculatedFieldLinkId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.HasId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.dao.asset.AssetProfileService;
 | 
			
		||||
import org.thingsboard.server.dao.asset.AssetService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceProfileService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.service.DataValidator;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@ -53,10 +45,6 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
 | 
			
		||||
 | 
			
		||||
    private final CalculatedFieldDao calculatedFieldDao;
 | 
			
		||||
    private final CalculatedFieldLinkDao calculatedFieldLinkDao;
 | 
			
		||||
    private final DeviceService deviceService;
 | 
			
		||||
    private final AssetService assetService;
 | 
			
		||||
    private final DeviceProfileService deviceProfileService;
 | 
			
		||||
    private final AssetProfileService assetProfileService;
 | 
			
		||||
    private final DataValidator<CalculatedField> calculatedFieldDataValidator;
 | 
			
		||||
    private final DataValidator<CalculatedFieldLink> calculatedFieldLinkDataValidator;
 | 
			
		||||
 | 
			
		||||
@ -65,7 +53,6 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
 | 
			
		||||
        calculatedFieldDataValidator.validate(calculatedField, CalculatedField::getTenantId);
 | 
			
		||||
        try {
 | 
			
		||||
            TenantId tenantId = calculatedField.getTenantId();
 | 
			
		||||
            checkEntityExistence(tenantId, calculatedField.getEntityId());
 | 
			
		||||
            log.trace("Executing save calculated field, [{}]", calculatedField);
 | 
			
		||||
            CalculatedField savedCalculatedField = calculatedFieldDao.save(tenantId, calculatedField);
 | 
			
		||||
            createOrUpdateCalculatedFieldLink(tenantId, savedCalculatedField);
 | 
			
		||||
@ -86,6 +73,12 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
 | 
			
		||||
        return calculatedFieldDao.findById(tenantId, calculatedFieldId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<CalculatedField> findAll() {
 | 
			
		||||
        log.trace("Executing findAll");
 | 
			
		||||
        return calculatedFieldDao.findAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId) {
 | 
			
		||||
        log.trace("Executing deleteCalculatedField, tenantId [{}], calculatedFieldId [{}]", tenantId, calculatedFieldId);
 | 
			
		||||
@ -123,6 +116,12 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
 | 
			
		||||
        return calculatedFieldLinkDao.findById(tenantId, calculatedFieldLinkId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<CalculatedFieldLink> findAllCalculatedFieldLinks() {
 | 
			
		||||
        log.trace("Executing findAllCalculatedFieldLinks");
 | 
			
		||||
        return calculatedFieldLinkDao.findAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean existsByEntityId(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
        return calculatedFieldDao.existsByTenantIdAndEntityId(tenantId, entityId);
 | 
			
		||||
@ -148,23 +147,6 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
 | 
			
		||||
        return EntityType.CALCULATED_FIELD;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkEntityExistence(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
        switch (entityId.getEntityType()) {
 | 
			
		||||
            case ASSET -> Optional.ofNullable(assetService.findAssetById(tenantId, (AssetId) entityId))
 | 
			
		||||
                    .orElseThrow(() -> new IllegalArgumentException("Asset with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            case DEVICE -> Optional.ofNullable(deviceService.findDeviceById(tenantId, (DeviceId) entityId))
 | 
			
		||||
                    .orElseThrow(() -> new IllegalArgumentException("Device with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            case ASSET_PROFILE ->
 | 
			
		||||
                    Optional.ofNullable(assetProfileService.findAssetProfileById(tenantId, (AssetProfileId) entityId))
 | 
			
		||||
                            .orElseThrow(() -> new IllegalArgumentException("Asset Profile with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            case DEVICE_PROFILE ->
 | 
			
		||||
                    Optional.ofNullable(deviceProfileService.findDeviceProfileById(tenantId, (DeviceProfileId) entityId))
 | 
			
		||||
                            .orElseThrow(() -> new IllegalArgumentException("Device Profile with id [" + entityId.getId() + "] does not exist."));
 | 
			
		||||
            default ->
 | 
			
		||||
                    throw new IllegalArgumentException("Entity type '" + entityId.getEntityType() + "' does not support calculated fields.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void createOrUpdateCalculatedFieldLink(TenantId tenantId, CalculatedField calculatedField) {
 | 
			
		||||
        CalculatedFieldLink existingLink = (calculatedField.getId() != null)
 | 
			
		||||
                ? calculatedFieldLinkDao.findCalculatedFieldLinkByCalculatedFieldId(tenantId, calculatedField.getId())
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,8 @@ public interface CalculatedFieldDao extends Dao<CalculatedField> {
 | 
			
		||||
 | 
			
		||||
    List<CalculatedField> findAllByTenantId(TenantId tenantId);
 | 
			
		||||
 | 
			
		||||
    List<CalculatedField> findAll();
 | 
			
		||||
 | 
			
		||||
    List<CalculatedField> removeAllByEntityId(TenantId tenantId, EntityId entityId);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,8 +20,12 @@ import org.thingsboard.server.common.data.id.CalculatedFieldId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.dao.Dao;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public interface CalculatedFieldLinkDao extends Dao<CalculatedFieldLink> {
 | 
			
		||||
 | 
			
		||||
    CalculatedFieldLink findCalculatedFieldLinkByCalculatedFieldId(TenantId tenantId, CalculatedFieldId calculatedFieldId);
 | 
			
		||||
 | 
			
		||||
    List<CalculatedFieldLink> findAll();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -51,6 +51,11 @@ public class JpaCalculatedFieldDao extends JpaAbstractDao<CalculatedFieldEntity,
 | 
			
		||||
        return DaoUtil.convertDataList(calculatedFieldRepository.findAllByTenantId(tenantId.getId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<CalculatedField> findAll() {
 | 
			
		||||
        return DaoUtil.convertDataList(calculatedFieldRepository.findAll());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public List<CalculatedField> removeAllByEntityId(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.sql.CalculatedFieldLinkEntity;
 | 
			
		||||
import org.thingsboard.server.dao.sql.JpaAbstractDao;
 | 
			
		||||
import org.thingsboard.server.dao.util.SqlDao;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
@ -44,6 +45,11 @@ public class JpaCalculatedFieldLinkDao extends JpaAbstractDao<CalculatedFieldLin
 | 
			
		||||
        return DaoUtil.getData(calculatedFieldLinkRepository.findByTenantIdAndCalculatedFieldId(tenantId.getId(), calculatedFieldId.getId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<CalculatedFieldLink> findAll() {
 | 
			
		||||
        return DaoUtil.convertDataList(calculatedFieldLinkRepository.findAll());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Class<CalculatedFieldLinkEntity> getEntityClass() {
 | 
			
		||||
        return CalculatedFieldLinkEntity.class;
 | 
			
		||||
 | 
			
		||||
@ -84,16 +84,6 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
 | 
			
		||||
        calculatedFieldService.deleteCalculatedField(tenantId, savedCalculatedField.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSaveCalculatesFieldWithNonExistingDeviceId() {
 | 
			
		||||
        DeviceId deviceId = new DeviceId(UUID.fromString("038f8668-c9fd-4f00-8501-ce20f2f93c22"));
 | 
			
		||||
        CalculatedField calculatedField = getCalculatedField(deviceId, deviceId);
 | 
			
		||||
 | 
			
		||||
        assertThatThrownBy(() -> calculatedFieldService.save(calculatedField))
 | 
			
		||||
                .isInstanceOf(IllegalArgumentException.class)
 | 
			
		||||
                .hasMessage("Device with id [" + calculatedField.getEntityId().getId() + "] does not exist.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSaveCalculatedFieldWithExistingName() {
 | 
			
		||||
        Device device = createTestDevice();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user