diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java index 14f98ca97d..042a9b1896 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageLink.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import org.springframework.data.domain.Sort; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -65,19 +66,19 @@ public class PageLink { return new PageLink(this.pageSize, this.page+1, this.textSearch, this.sortOrder); } - public Sort toSort(SortOrder sortOrder, Map columnMap) { + public Sort toSort(SortOrder sortOrder, Map columnMap, boolean addDefaultSorting) { if (sortOrder == null) { return DEFAULT_SORT; } else { - String property = sortOrder.getProperty(); - if (columnMap.containsKey(property)) { - property = columnMap.get(property); - } - return Sort.by(Sort.Direction.fromString(sortOrder.getDirection().name()), property); + return toSort(List.of(sortOrder), columnMap, addDefaultSorting); } } - public Sort toSort(List sortOrders, Map columnMap) { + public Sort toSort(List sortOrders, Map columnMap, boolean addDefaultSorting) { + if (addDefaultSorting && !isDefaultSortOrderAvailable(sortOrders)) { + sortOrders = new ArrayList<>(sortOrders); + sortOrders.add(new SortOrder(DEFAULT_SORT_PROPERTY, SortOrder.Direction.ASC)); + } return Sort.by(sortOrders.stream().map(s -> toSortOrder(s, columnMap)).collect(Collectors.toList())); } @@ -86,7 +87,16 @@ public class PageLink { if (columnMap.containsKey(property)) { property = columnMap.get(property); } - return new Sort.Order(Sort.Direction.fromString(sortOrder.getDirection().name()), property, Sort.NullHandling.NULLS_LAST); + return new Sort.Order(Sort.Direction.fromString(sortOrder.getDirection().name()), property); + } + + public boolean isDefaultSortOrderAvailable(List sortOrders) { + for (SortOrder sortOrder : sortOrders) { + if (DEFAULT_SORT_PROPERTY.equals(sortOrder.getProperty())) { + return true; + } + } + return false; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java index c9dacbff40..365d4f7e35 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java @@ -19,11 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.springframework.data.domain.Sort; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; @Data @ToString(callSuper = true) @@ -67,29 +62,4 @@ public class TimePageLink extends PageLink { this.startTime, this.endTime); } - @Override - public Sort toSort(SortOrder sortOrder, Map columnMap) { - if (sortOrder == null) { - return super.toSort(sortOrder, columnMap); - } else { - return toSort(new ArrayList<>(List.of(sortOrder)), columnMap); - } - } - - @Override - public Sort toSort(List sortOrders, Map columnMap) { - if (!isDefaultSortOrderAvailable(sortOrders)) { - sortOrders.add(new SortOrder(DEFAULT_SORT_PROPERTY, SortOrder.Direction.ASC)); - } - return super.toSort(sortOrders, columnMap); - } - - private boolean isDefaultSortOrderAvailable(List sortOrders) { - for (SortOrder sortOrder : sortOrders) { - if (DEFAULT_SORT_PROPERTY.equals(sortOrder.getProperty())) { - return true; - } - } - return false; - } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java index 0e7fe8f108..865306c73b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java @@ -56,11 +56,19 @@ public abstract class DaoUtil { } public static Pageable toPageable(PageLink pageLink) { - return toPageable(pageLink, Collections.emptyMap()); + return toPageable(pageLink, true); + } + + public static Pageable toPageable(PageLink pageLink, boolean addDefaultSorting) { + return toPageable(pageLink, Collections.emptyMap(), addDefaultSorting); } public static Pageable toPageable(PageLink pageLink, Map columnMap) { - return PageRequest.of(pageLink.getPage(), pageLink.getPageSize(), pageLink.toSort(pageLink.getSortOrder(), columnMap)); + return toPageable(pageLink, columnMap, true); + } + + public static Pageable toPageable(PageLink pageLink, Map columnMap, boolean addDefaultSorting) { + return PageRequest.of(pageLink.getPage(), pageLink.getPageSize(), pageLink.toSort(pageLink.getSortOrder(), columnMap, addDefaultSorting)); } public static Pageable toPageable(PageLink pageLink, List sortOrders) { @@ -68,7 +76,11 @@ public abstract class DaoUtil { } public static Pageable toPageable(PageLink pageLink, Map columnMap, List sortOrders) { - return PageRequest.of(pageLink.getPage(), pageLink.getPageSize(), pageLink.toSort(sortOrders, columnMap)); + return toPageable(pageLink, columnMap, sortOrders, true); + } + + public static Pageable toPageable(PageLink pageLink, Map columnMap, List sortOrders, boolean addDefaultSorting) { + return PageRequest.of(pageLink.getPage(), pageLink.getPageSize(), pageLink.toSort(sortOrders, columnMap, addDefaultSorting)); } public static List convertDataList(Collection> toDataList) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 9430773ff9..15d4602230 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -383,7 +383,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A @Override public PageData findTenantAlarmTypes(UUID tenantId, PageLink pageLink) { - Page page = alarmRepository.findTenantAlarmTypes(tenantId, Objects.toString(pageLink.getTextSearch(), ""), toPageable(pageLink)); + Page page = alarmRepository.findTenantAlarmTypes(tenantId, Objects.toString(pageLink.getTextSearch(), ""), toPageable(pageLink, false)); if (page.isEmpty()) { return PageData.emptyPageData(); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java index acff0902f1..e8f3bba9db 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java @@ -21,6 +21,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.page.PageData; @@ -43,6 +44,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; @@ -160,6 +162,30 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest { assertEquals(new WidgetTypeInfo(widgetTypeList.get(2)), widgetTypes.getData().get(0)); } + @Test + public void testFindSystemWidgetTypesForSameName() throws InterruptedException { + List sameNameList = new ArrayList<>(); + + for (int i = 0; i < 20; i++) { + Thread.sleep(2); + var widgetType = saveWidgetType(TenantId.SYS_TENANT_ID, "widgetName"); + sameNameList.add(widgetType); + widgetTypeList.add(widgetType); + } + sameNameList.sort(Comparator.comparing(BaseWidgetType::getName).thenComparing((BaseWidgetType baseWidgetType) -> baseWidgetType.getId().getId())); + List expected = sameNameList.stream().map(WidgetTypeInfo::new).collect(Collectors.toList()); + + PageData widgetTypesFirstPage = widgetTypeDao.findSystemWidgetTypes(TenantId.SYS_TENANT_ID, true, DeprecatedFilter.ALL, Collections.singletonList("static"), + new PageLink(10, 0, null, new SortOrder("name"))); + assertEquals(10, widgetTypesFirstPage.getData().size()); + assertThat(widgetTypesFirstPage.getData()).containsExactlyElementsOf(expected.subList(0, 10)); + + PageData widgetTypesSecondPage = widgetTypeDao.findSystemWidgetTypes(TenantId.SYS_TENANT_ID, true, DeprecatedFilter.ALL, Collections.singletonList("static"), + new PageLink(10, 1, null, new SortOrder("name"))); + assertEquals(10, widgetTypesSecondPage.getData().size()); + assertThat(widgetTypesSecondPage.getData()).containsExactlyElementsOf(expected.subList(10, 20)); + } + @Test public void testTagsSearchInFindBySystemWidgetTypes() { for (var entry : SHOULD_FIND_SEARCH_TO_TAGS_MAP.entrySet()) { @@ -355,4 +381,15 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest { assertEquals(0, result.size()); widgetTypeDao.removeById(tenantId, details.getUuidId()); } + + private WidgetTypeDetails saveWidgetType(TenantId tenantId, String name) { + WidgetTypeDetails widgetType = new WidgetTypeDetails(); + widgetType.setTenantId(tenantId); + widgetType.setDescription("WIDGET_TYPE_DESCRIPTION" + StringUtils.randomAlphabetic(7)); + widgetType.setName(name); + var descriptor = JacksonUtil.newObjectNode(); + descriptor.put("type","static"); + widgetType.setDescriptor(descriptor); + return widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType); + } }