added tbCalculatedField Service

This commit is contained in:
IrynaMatveieva 2024-11-07 14:07:58 +02:00
parent 4dbc35273a
commit bcef71f78d
11 changed files with 270 additions and 73 deletions

View File

@ -27,23 +27,14 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; 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.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldConfig;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CalculatedFieldId; 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.config.annotations.ApiOperation;
import org.thingsboard.server.dao.cf.CalculatedFieldService;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.cf.TbCalculatedFieldService;
import org.thingsboard.server.service.security.permission.Operation; 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.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; 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 @Slf4j
public class CalculatedFieldController extends BaseController { public class CalculatedFieldController extends BaseController {
private static final Set<EntityType> supportedEntityTypesForReferencedEntities = EnumSet.of( private final TbCalculatedFieldService tbCalculatedFieldService;
EntityType.TENANT, EntityType.CUSTOMER, EntityType.ASSET, EntityType.DEVICE);
private final CalculatedFieldService calculatedFieldService;
public static final String CALCULATED_FIELD_ID = "calculatedFieldId"; public static final String CALCULATED_FIELD_ID = "calculatedFieldId";
@ -75,8 +63,7 @@ public class CalculatedFieldController extends BaseController {
@RequestBody CalculatedField calculatedField) throws Exception { @RequestBody CalculatedField calculatedField) throws Exception {
calculatedField.setTenantId(getTenantId()); calculatedField.setTenantId(getTenantId());
checkEntityId(calculatedField.getEntityId(), Operation.WRITE_CALCULATED_FIELD); checkEntityId(calculatedField.getEntityId(), Operation.WRITE_CALCULATED_FIELD);
checkReferencedEntities(calculatedField.getConfiguration()); return tbCalculatedFieldService.save(calculatedField, getCurrentUser());
return calculatedFieldService.save(calculatedField);
} }
@ApiOperation(value = "Get Calculated Field (getCalculatedFieldById)", @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 { public CalculatedField getCalculatedFieldById(@Parameter @PathVariable(CALCULATED_FIELD_ID) String strCalculatedFieldId) throws ThingsboardException {
checkParameter(CALCULATED_FIELD_ID, strCalculatedFieldId); checkParameter(CALCULATED_FIELD_ID, strCalculatedFieldId);
CalculatedFieldId calculatedFieldId = new CalculatedFieldId(toUUID(strCalculatedFieldId)); CalculatedFieldId calculatedFieldId = new CalculatedFieldId(toUUID(strCalculatedFieldId));
CalculatedField calculatedField = calculatedFieldService.findById(getTenantId(), calculatedFieldId); CalculatedField calculatedField = tbCalculatedFieldService.findById(calculatedFieldId, getCurrentUser());
checkNotNull(calculatedField); checkNotNull(calculatedField);
checkEntityId(calculatedField.getEntityId(), Operation.READ_CALCULATED_FIELD); checkEntityId(calculatedField.getEntityId(), Operation.READ_CALCULATED_FIELD);
return calculatedField; return calculatedField;
@ -103,23 +90,9 @@ public class CalculatedFieldController extends BaseController {
public void deleteCalculatedField(@PathVariable(CALCULATED_FIELD_ID) String strCalculatedField) throws Exception { public void deleteCalculatedField(@PathVariable(CALCULATED_FIELD_ID) String strCalculatedField) throws Exception {
checkParameter(CALCULATED_FIELD_ID, strCalculatedField); checkParameter(CALCULATED_FIELD_ID, strCalculatedField);
CalculatedFieldId calculatedFieldId = new CalculatedFieldId(toUUID(strCalculatedField)); CalculatedFieldId calculatedFieldId = new CalculatedFieldId(toUUID(strCalculatedField));
TenantId tenantId = getTenantId(); CalculatedField calculatedField = tbCalculatedFieldService.findById(calculatedFieldId, getCurrentUser());
CalculatedField calculatedField = calculatedFieldService.findById(tenantId, calculatedFieldId);
checkEntityId(calculatedField.getEntityId(), Operation.WRITE_CALCULATED_FIELD); checkEntityId(calculatedField.getEntityId(), Operation.WRITE_CALCULATED_FIELD);
calculatedFieldService.deleteCalculatedField(getTenantId(), calculatedFieldId); tbCalculatedFieldService.delete(calculatedField, getCurrentUser());
}
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);
}
} }
} }

View File

@ -25,16 +25,30 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.EntityType; 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.User;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory; 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.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.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.edge.EdgeService;
import org.thingsboard.server.dao.model.ModelConstants; 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.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.sync.vc.EntitiesVersionControlService;
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
@ -43,6 +57,8 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Slf4j @Slf4j
public abstract class AbstractTbEntityService { public abstract class AbstractTbEntityService {
@ -71,6 +87,18 @@ public abstract class AbstractTbEntityService {
@Autowired(required = false) @Autowired(required = false)
@Lazy @Lazy
private EntitiesVersionControlService vcService; 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() { protected boolean isTestProfile() {
return Set.of(this.env.getActiveProfiles()).contains("test"); return Set.of(this.env.getActiveProfiles()).contains("test");
@ -120,4 +148,23 @@ public abstract class AbstractTbEntityService {
return Futures.immediateFailedFuture(new RuntimeException("Operation not supported!")); 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;
}
} }

View File

@ -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.");
};
}
}

View File

@ -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);
}

View File

@ -23,12 +23,16 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entity.EntityDaoService; import org.thingsboard.server.dao.entity.EntityDaoService;
import java.util.List;
public interface CalculatedFieldService extends EntityDaoService { public interface CalculatedFieldService extends EntityDaoService {
CalculatedField save(CalculatedField calculatedField); CalculatedField save(CalculatedField calculatedField);
CalculatedField findById(TenantId tenantId, CalculatedFieldId calculatedFieldId); CalculatedField findById(TenantId tenantId, CalculatedFieldId calculatedFieldId);
List<CalculatedField> findAll();
void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId); void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId);
int deleteAllCalculatedFieldsByEntityId(TenantId tenantId, EntityId entityId); int deleteAllCalculatedFieldsByEntityId(TenantId tenantId, EntityId entityId);
@ -37,6 +41,8 @@ public interface CalculatedFieldService extends EntityDaoService {
CalculatedFieldLink findCalculatedFieldLinkById(TenantId tenantId, CalculatedFieldLinkId calculatedFieldLinkId); CalculatedFieldLink findCalculatedFieldLinkById(TenantId tenantId, CalculatedFieldLinkId calculatedFieldLinkId);
List<CalculatedFieldLink> findAllCalculatedFieldLinks();
boolean existsByEntityId(TenantId tenantId, EntityId entityId); boolean existsByEntityId(TenantId tenantId, EntityId entityId);
boolean referencedInAnyCalculatedField(TenantId tenantId, EntityId referencedEntityId); boolean referencedInAnyCalculatedField(TenantId tenantId, EntityId referencedEntityId);

View File

@ -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.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldConfig; import org.thingsboard.server.common.data.cf.CalculatedFieldConfig;
import org.thingsboard.server.common.data.cf.CalculatedFieldLink; 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.CalculatedFieldId;
import org.thingsboard.server.common.data.id.CalculatedFieldLinkId; 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.EntityId;
import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId; 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 org.thingsboard.server.dao.service.DataValidator;
import java.util.List; import java.util.List;
@ -53,10 +45,6 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
private final CalculatedFieldDao calculatedFieldDao; private final CalculatedFieldDao calculatedFieldDao;
private final CalculatedFieldLinkDao calculatedFieldLinkDao; 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<CalculatedField> calculatedFieldDataValidator;
private final DataValidator<CalculatedFieldLink> calculatedFieldLinkDataValidator; private final DataValidator<CalculatedFieldLink> calculatedFieldLinkDataValidator;
@ -65,7 +53,6 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
calculatedFieldDataValidator.validate(calculatedField, CalculatedField::getTenantId); calculatedFieldDataValidator.validate(calculatedField, CalculatedField::getTenantId);
try { try {
TenantId tenantId = calculatedField.getTenantId(); TenantId tenantId = calculatedField.getTenantId();
checkEntityExistence(tenantId, calculatedField.getEntityId());
log.trace("Executing save calculated field, [{}]", calculatedField); log.trace("Executing save calculated field, [{}]", calculatedField);
CalculatedField savedCalculatedField = calculatedFieldDao.save(tenantId, calculatedField); CalculatedField savedCalculatedField = calculatedFieldDao.save(tenantId, calculatedField);
createOrUpdateCalculatedFieldLink(tenantId, savedCalculatedField); createOrUpdateCalculatedFieldLink(tenantId, savedCalculatedField);
@ -86,6 +73,12 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
return calculatedFieldDao.findById(tenantId, calculatedFieldId.getId()); return calculatedFieldDao.findById(tenantId, calculatedFieldId.getId());
} }
@Override
public List<CalculatedField> findAll() {
log.trace("Executing findAll");
return calculatedFieldDao.findAll();
}
@Override @Override
public void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId) { public void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId) {
log.trace("Executing deleteCalculatedField, tenantId [{}], calculatedFieldId [{}]", tenantId, calculatedFieldId); log.trace("Executing deleteCalculatedField, tenantId [{}], calculatedFieldId [{}]", tenantId, calculatedFieldId);
@ -123,6 +116,12 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
return calculatedFieldLinkDao.findById(tenantId, calculatedFieldLinkId.getId()); return calculatedFieldLinkDao.findById(tenantId, calculatedFieldLinkId.getId());
} }
@Override
public List<CalculatedFieldLink> findAllCalculatedFieldLinks() {
log.trace("Executing findAllCalculatedFieldLinks");
return calculatedFieldLinkDao.findAll();
}
@Override @Override
public boolean existsByEntityId(TenantId tenantId, EntityId entityId) { public boolean existsByEntityId(TenantId tenantId, EntityId entityId) {
return calculatedFieldDao.existsByTenantIdAndEntityId(tenantId, entityId); return calculatedFieldDao.existsByTenantIdAndEntityId(tenantId, entityId);
@ -148,23 +147,6 @@ public class BaseCalculatedFieldService implements CalculatedFieldService {
return EntityType.CALCULATED_FIELD; 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) { private void createOrUpdateCalculatedFieldLink(TenantId tenantId, CalculatedField calculatedField) {
CalculatedFieldLink existingLink = (calculatedField.getId() != null) CalculatedFieldLink existingLink = (calculatedField.getId() != null)
? calculatedFieldLinkDao.findCalculatedFieldLinkByCalculatedFieldId(tenantId, calculatedField.getId()) ? calculatedFieldLinkDao.findCalculatedFieldLinkByCalculatedFieldId(tenantId, calculatedField.getId())

View File

@ -28,6 +28,8 @@ public interface CalculatedFieldDao extends Dao<CalculatedField> {
List<CalculatedField> findAllByTenantId(TenantId tenantId); List<CalculatedField> findAllByTenantId(TenantId tenantId);
List<CalculatedField> findAll();
List<CalculatedField> removeAllByEntityId(TenantId tenantId, EntityId entityId); List<CalculatedField> removeAllByEntityId(TenantId tenantId, EntityId entityId);
} }

View File

@ -20,8 +20,12 @@ import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.Dao;
import java.util.List;
public interface CalculatedFieldLinkDao extends Dao<CalculatedFieldLink> { public interface CalculatedFieldLinkDao extends Dao<CalculatedFieldLink> {
CalculatedFieldLink findCalculatedFieldLinkByCalculatedFieldId(TenantId tenantId, CalculatedFieldId calculatedFieldId); CalculatedFieldLink findCalculatedFieldLinkByCalculatedFieldId(TenantId tenantId, CalculatedFieldId calculatedFieldId);
List<CalculatedFieldLink> findAll();
} }

View File

@ -51,6 +51,11 @@ public class JpaCalculatedFieldDao extends JpaAbstractDao<CalculatedFieldEntity,
return DaoUtil.convertDataList(calculatedFieldRepository.findAllByTenantId(tenantId.getId())); return DaoUtil.convertDataList(calculatedFieldRepository.findAllByTenantId(tenantId.getId()));
} }
@Override
public List<CalculatedField> findAll() {
return DaoUtil.convertDataList(calculatedFieldRepository.findAll());
}
@Override @Override
@Transactional @Transactional
public List<CalculatedField> removeAllByEntityId(TenantId tenantId, EntityId entityId) { public List<CalculatedField> removeAllByEntityId(TenantId tenantId, EntityId entityId) {

View File

@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.sql.CalculatedFieldLinkEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Slf4j @Slf4j
@ -44,6 +45,11 @@ public class JpaCalculatedFieldLinkDao extends JpaAbstractDao<CalculatedFieldLin
return DaoUtil.getData(calculatedFieldLinkRepository.findByTenantIdAndCalculatedFieldId(tenantId.getId(), calculatedFieldId.getId())); return DaoUtil.getData(calculatedFieldLinkRepository.findByTenantIdAndCalculatedFieldId(tenantId.getId(), calculatedFieldId.getId()));
} }
@Override
public List<CalculatedFieldLink> findAll() {
return DaoUtil.convertDataList(calculatedFieldLinkRepository.findAll());
}
@Override @Override
protected Class<CalculatedFieldLinkEntity> getEntityClass() { protected Class<CalculatedFieldLinkEntity> getEntityClass() {
return CalculatedFieldLinkEntity.class; return CalculatedFieldLinkEntity.class;

View File

@ -84,16 +84,6 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
calculatedFieldService.deleteCalculatedField(tenantId, savedCalculatedField.getId()); 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 @Test
public void testSaveCalculatedFieldWithExistingName() { public void testSaveCalculatedFieldWithExistingName() {
Device device = createTestDevice(); Device device = createTestDevice();