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.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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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.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);
|
||||||
|
|||||||
@ -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())
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user