Browse Source

Enhance calculated fields filter API

pull/14609/head
Viacheslav Klimov 7 months ago
parent
commit
872fc0803f
  1. 22
      application/src/main/java/org/thingsboard/server/controller/CalculatedFieldController.java
  2. 3
      application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
  3. 2
      application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java
  4. 7
      common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedFieldFilter.java
  5. 9
      dao/src/main/java/org/thingsboard/server/dao/sql/cf/CalculatedFieldRepository.java
  6. 3
      dao/src/main/java/org/thingsboard/server/dao/sql/cf/JpaCalculatedFieldDao.java

22
application/src/main/java/org/thingsboard/server/controller/CalculatedFieldController.java

@ -21,6 +21,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.HttpStatus;
@ -68,7 +69,7 @@ import org.thingsboard.server.service.security.permission.Operation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@ -198,12 +199,12 @@ public class CalculatedFieldController extends BaseController {
@RequestParam int pageSize,
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@Parameter(description = "Calculated field type filter.")
@RequestParam CalculatedFieldType type,
@Parameter(description = "Calculated field types filter.")
@RequestParam(required = false) Set<CalculatedFieldType> types,
@Parameter(description = "Entity type filter. If not specified, calculated fields for all supported entity types will be returned.")
@RequestParam(required = false) EntityType entityType,
@Parameter(description = "Entities filter. If not specified, calculated fields for entity type filter will be returned.")
@RequestParam(required = false) List<UUID> entities,
@RequestParam(required = false) Set<UUID> entities,
@Parameter(description = "Name filter. To specify multiple names, duplicate 'name' parameter for each name, for example '?name=name1&name=name2")
@RequestParam(required = false) String name, // for Swagger only, retrieved from MultiValueMap params (due to issues when name contains comma)
@Parameter(description = CF_TEXT_SEARCH_DESCRIPTION)
@ -215,6 +216,12 @@ public class CalculatedFieldController extends BaseController {
@RequestParam MultiValueMap<String, String> params) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
SecurityUser user = getCurrentUser();
if (CollectionUtils.isEmpty(types)) {
types = EnumSet.allOf(CalculatedFieldType.class);
types.remove(CalculatedFieldType.ALARM);
}
Set<EntityType> entityTypes;
if (entityType == null) {
entityTypes = CalculatedField.SUPPORTED_ENTITIES.keySet();
@ -223,10 +230,10 @@ public class CalculatedFieldController extends BaseController {
}
CalculatedFieldFilter filter = CalculatedFieldFilter.builder()
.type(type)
.types(types)
.entityTypes(entityTypes)
.entityIds(entities)
.names(params.get("name"))
.names(Optional.ofNullable(params.get("name")).map(HashSet::new).orElse(null))
.build();
return calculatedFieldService.findCalculatedFieldsByTenantIdAndFilter(user.getTenantId(), filter, pageLink);
}
@ -361,8 +368,7 @@ public class CalculatedFieldController extends BaseController {
return;
}
case CUSTOMER, ASSET, DEVICE -> checkEntityId(referencedEntityId, Operation.READ);
default ->
throw new IllegalArgumentException("Calculated fields do not support '" + entityType + "' for referenced entities.");
default -> throw new IllegalArgumentException("Calculated fields do not support '" + entityType + "' for referenced entities.");
}
}
}

3
application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java

@ -1441,7 +1441,8 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
EntityType entityType,
List<UUID> entities,
List<String> names) throws Exception {
return doGetTypedWithPageLink("/api/calculatedFields?type=" + type + "&" +
return doGetTypedWithPageLink("/api/calculatedFields?" +
(type != null ? "types=" + type + "&" : "") +
(entityType != null ? "entityType=" + entityType + "&" : "") +
(entities != null ? "entities=" + String.join(",",
entities.stream().map(UUID::toString).toList()) + "&" : "") +

2
application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java

@ -259,6 +259,8 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest {
List<CalculatedFieldInfo> allCalculatedFields = getCalculatedFields(CalculatedFieldType.SIMPLE,
null, null, null);
assertThat(allCalculatedFields).contains(deviceCalculatedField, profileCalculatedField);
allCalculatedFields = getCalculatedFields(null, null, null, null);
assertThat(allCalculatedFields).contains(deviceCalculatedField, profileCalculatedField);
List<CalculatedFieldInfo> profileLevelCalculatedFields = getCalculatedFields(CalculatedFieldType.SIMPLE,
EntityType.DEVICE_PROFILE, null, null);

7
common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedFieldFilter.java

@ -21,7 +21,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.thingsboard.server.common.data.EntityType;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@ -30,12 +29,12 @@ import java.util.UUID;
public class CalculatedFieldFilter {
@NonNull
private final CalculatedFieldType type;
private final Set<CalculatedFieldType> types;
@NonNull
private final Set<EntityType> entityTypes;
@Nullable
private final List<UUID> entityIds;
private final Set<UUID> entityIds;
@Nullable
private final List<String> names;
private final Set<String> names;
}

9
dao/src/main/java/org/thingsboard/server/dao/sql/cf/CalculatedFieldRepository.java

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.dao.model.sql.CalculatedFieldEntity;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public interface CalculatedFieldRepository extends JpaRepository<CalculatedFieldEntity, UUID> {
@ -43,18 +44,18 @@ public interface CalculatedFieldRepository extends JpaRepository<CalculatedField
Page<CalculatedFieldEntity> findByTenantIdAndEntityIdAndTypes(UUID tenantId, UUID entityId, List<String> types, String textSearch, Pageable pageable);
@Query("SELECT cf FROM CalculatedFieldEntity cf WHERE cf.tenantId = :tenantId " +
"AND cf.type = :type " +
"AND cf.type IN :types " +
"AND cf.entityType IN :entityTypes " +
"AND (:entityIds IS NULL OR cf.entityId IN :entityIds) " +
"AND (:names IS NULL OR cf.name IN :names) " +
"AND (:textSearch IS NULL OR ilike(cf.name, CONCAT('%', :textSearch, '%')) = true)")
Page<CalculatedFieldEntity> findByTenantIdAndFilter(UUID tenantId, String type, List<String> entityTypes,
List<UUID> entityIds, List<String> names, String textSearch, Pageable pageable);
Page<CalculatedFieldEntity> findByTenantIdAndFilter(UUID tenantId, List<String> types, List<String> entityTypes,
Set<UUID> entityIds, Set<String> names, String textSearch, Pageable pageable);
@Query("SELECT DISTINCT cf.name FROM CalculatedFieldEntity cf " +
"WHERE cf.tenantId = :tenantId AND cf.type = :type AND " +
"(:textSearch IS NULL OR ilike(cf.name, CONCAT('%', :textSearch, '%')) = true)")
Page<String> findNamesByTenantIdAndType(UUID tenantId, String type,String textSearch, Pageable pageable);
Page<String> findNamesByTenantIdAndType(UUID tenantId, String type, String textSearch, Pageable pageable);
List<CalculatedFieldEntity> findAllByTenantId(UUID tenantId);

3
dao/src/main/java/org/thingsboard/server/dao/sql/cf/JpaCalculatedFieldDao.java

@ -107,7 +107,8 @@ public class JpaCalculatedFieldDao extends JpaAbstractDao<CalculatedFieldEntity,
@Override
public PageData<CalculatedField> findByTenantIdAndFilter(TenantId tenantId, CalculatedFieldFilter filter, PageLink pageLink) {
return DaoUtil.toPageData(calculatedFieldRepository.findByTenantIdAndFilter(tenantId.getId(), filter.getType().name(),
return DaoUtil.toPageData(calculatedFieldRepository.findByTenantIdAndFilter(tenantId.getId(),
filter.getTypes().stream().map(Enum::name).toList(),
filter.getEntityTypes().stream().map(Enum::name).toList(),
CollectionUtils.isNotEmpty(filter.getEntityIds()) ? filter.getEntityIds() : null,
CollectionUtils.isNotEmpty(filter.getNames()) ? filter.getNames() : null,

Loading…
Cancel
Save