Dbeaver/dbeaver#38331 case insensitive tables order (#39351)

* dbeaver/dbeaver#38331: add empty tests

* dbeaver/dbeaver#38331: add tests

* dbeaver/dbeaver#38331: add no sort tests

* dbeaver/dbeaver#38331: add property case insensitive

* dbeaver/dbeaver#38331: add node name comparator logic

* dbeaver/dbeaver#38331: add wording for DB navigator en,ru,es

* dbeaver/dbeaver#38331: add checkbox for selection

* dbeaver/dbeaver#38331: fix NodeName init

* dbeaver/dbeaver#38331: add compare ignore case to Alphanumeric

* dbeaver/dbeaver#38331: fix checkstyle

* dbeaver/dbeaver#38331: fix codacy test complaints

* dbeaver/dbeaver#38331: fix codacy tests naming

* dbeaver/dbeaver#38331: fix codacy tests naming

---------

Co-authored-by: Diana <31996417+uslss@users.noreply.github.com>
This commit is contained in:
Solovev Anton
2025-10-09 17:16:39 +02:00
committed by GitHub
parent 8cb014551f
commit e972cdc22a
15 changed files with 547 additions and 58 deletions

View File

@@ -24,4 +24,5 @@
<plugin id="org.jkiss.dbeaver.ext.clickhouse.test" version="0.0.0"/>
<plugin id="org.jkiss.dbeaver.ext.generic.test" version="0.0.0"/>
<plugin id="org.jkiss.dbeaver.model.ai.test" version="0.0.0"/>
<plugin id="org.jkiss.dbeaver.model.navigator.test" version="0.0.0"/>
</feature>

View File

@@ -266,6 +266,7 @@ public final class ModelPreferences
public static final String NAVIGATOR_SHOW_FOLDER_PLACEHOLDERS = "navigator.show.folder.placeholders"; //$NON-NLS-1$
public static final String NAVIGATOR_SORT_ALPHABETICALLY = "navigator.sort.case.insensitive"; //$NON-NLS-1$
public static final String NAVIGATOR_SORT_IGNORE_CASE = "navigator.sort.case.insensitive.ignore.case"; //$NON-NLS-1$
public static final String NAVIGATOR_SORT_FOLDERS_FIRST = "navigator.sort.forlers.first"; //$NON-NLS-1$
public static final String PLATFORM_LANGUAGE = "platform.language"; //$NON-NLS-1$
@@ -402,6 +403,7 @@ public final class ModelPreferences
PrefUtils.setDefaultPreferenceValue(store, ModelPreferences.NAVIGATOR_SHOW_FOLDER_PLACEHOLDERS, true);
PrefUtils.setDefaultPreferenceValue(store, ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, false);
PrefUtils.setDefaultPreferenceValue(store, ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE, false);
PrefUtils.setDefaultPreferenceValue(store, ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST, true);
PrefUtils.setDefaultPreferenceValue(store, ModelPreferences.TRANSACTIONS_SMART_COMMIT, false);

View File

@@ -160,10 +160,6 @@ public class DBNUtils {
Comparator<DBNNode> comparator = null;
if (prefStore.getBoolean(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY)) {
comparator = NodeNameComparator.INSTANCE;
}
if (prefStore.getBoolean(ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST) || isMergedEntity(firstChild)) {
comparator = NodeFolderComparator.INSTANCE.thenComparing((o1, o2) -> {
if (o1 instanceof DBNContainer && o2 instanceof DBNContainer) {
@@ -173,10 +169,16 @@ public class DBNUtils {
} else if (o2 instanceof DBNContainer) {
return -1;
}
return AlphanumericComparator.getInstance()
.compare(o1.getNodeDisplayName(), o2.getNodeDisplayName());
return 0;
});
}
if (prefStore.getBoolean(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY)) {
comparator = Objects.isNull(comparator)
? NodeNameComparator.INSTANCE
: comparator.thenComparing(NodeNameComparator.INSTANCE);
}
if (comparator != null) {
Arrays.sort(children, comparator);
}
@@ -271,10 +273,14 @@ public class DBNUtils {
private static class NodeNameComparator implements Comparator<DBNNode> {
static NodeNameComparator INSTANCE = new NodeNameComparator();
private final DBPPreferenceStore prefStore = DBWorkbench.getPlatform().getPreferenceStore();
private final AlphanumericComparator alphanumericComparator = AlphanumericComparator.getInstance();
@Override
public int compare(DBNNode node1, DBNNode node2) {
return node1.getNodeDisplayName().compareToIgnoreCase(node2.getNodeDisplayName());
return prefStore.getBoolean(ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE)
? alphanumericComparator.compareIgnoreCase(node1.getNodeDisplayName(), node2.getNodeDisplayName())
: alphanumericComparator.compare(node1.getNodeDisplayName(), node2.getNodeDisplayName());
}
}

View File

@@ -128,6 +128,8 @@ public class UINavigatorMessages extends NLS {
public static String pref_page_database_general_label_show_contents_in_tooltips_tip;
public static String pref_page_database_general_label_order_elements_alphabetically;
public static String pref_page_database_general_label_order_elements_alphabetically_tip;
public static String pref_page_database_general_label_sort_case_insensitive;
public static String pref_page_database_general_label_sort_case_insensitive_tip;
public static String pref_page_database_general_label_folders_first;
public static String pref_page_database_general_label_folders_first_tip;
public static String pref_page_database_general_label_show_host_name;

View File

@@ -108,6 +108,8 @@ pref_page_ui_general_show_table_grid = Show grid lines in lists
pref_page_database_general_label_order_elements_alphabetically = Order elements alphabetically
pref_page_database_general_label_order_elements_alphabetically_tip = Order navigator nodes (not folders) alphabetically.
pref_page_database_general_label_sort_case_insensitive = Case-insensitive alphabetical sorting
pref_page_database_general_label_sort_case_insensitive_tip = Order navigator nodes without case sensitivity Ex: A,a,B,b
pref_page_database_general_label_folders_first = Folders first
pref_page_database_general_label_folders_first_tip = Show folders before regular elements
pref_page_database_general_label_show_child_count = Show child count in navigator

View File

@@ -245,8 +245,20 @@ pref_page_database_navigator_group_misc = Misceláneo
pref_page_navigator_default_editor_page_label = Página de editor por defecto
pref_page_database_general_label_restore_filter = Guardar filtro del navegador de base de datos
pref_page_database_general_label_restore_filter_tip = Guarda el filtro de objetos especificado en la vista del navegador de base de datos entre reinicios de la aplicación
pref_page_navigator_default_editor_page_tip = Activa la página especificada en los editores de objetos. Si no se especifica, activa la página por defecto
pref_page_database_general_label_sort_case_insensitive = Ordenar alfabéticamente sin distinguir mayúsculas y minúsculas
pref_page_database_general_label_sort_case_insensitive_tip = Ordenar los nodos del navegador sin distinguir mayúsculas y minúsculas. Ej: A,a,B,b
pref_page_database_general_label_show_child_count = Mostrar cantidad de hijos en el navegador
pref_page_database_general_label_show_child_count_tip = Mostrar la cantidad de hijos para carpetas expandidas en el árbol del navegador
pref_page_projects_settings_label_folder = Carpeta
pref_page_projects_settings_label_not_store_resources_in_another_project = No se puede guardar recursos en otro proyecto

View File

@@ -69,6 +69,8 @@ pref_page_database_general_label_show_tooltips_tip = Показывать всп
pref_page_database_general_label_show_contents_in_tooltips = Показывать содержимое файлов в подсказках
pref_page_database_general_label_show_contents_in_tooltips_tip = Показывать содержимое файлов (напр. SQL скриптов) в всплывающих подсказках
pref_page_database_general_label_order_elements_alphabetically = Упорядочить элементы по алфавиту
pref_page_database_general_label_sort_case_insensitive = Алфавитная сортировка без учета регистра
pref_page_database_general_label_sort_case_insensitive_tip = Упорядочивать узлы навигатора без учета регистра. Например: A,a,B,b
pref_page_database_general_label_folders_first = Сначала папки
pref_page_database_general_label_folders_first_tip = Показывать папки перед обычными элементами
pref_page_database_general_label_group_database_by_driver = Группировать базы данных по драйверам

View File

@@ -349,6 +349,7 @@ public abstract class NavigatorViewBase extends ViewPart
switch (property) {
case ModelPreferences.NAVIGATOR_SHOW_FOLDER_PLACEHOLDERS:
case ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY:
case ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE:
case ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST:
case NavigatorPreferences.NAVIGATOR_COLOR_ALL_NODES:
case NavigatorPreferences.NAVIGATOR_GROUP_BY_DRIVER:

View File

@@ -18,6 +18,7 @@ package org.jkiss.dbeaver.ui.preferences;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.IWorkbench;
@@ -55,6 +56,7 @@ public class PrefPageDatabaseNavigator extends AbstractPrefPage implements IWork
private Button expandOnConnectCheck;
private Button restoreFilterCheck;
private Text restoreStateDepthText;
private Button sortAlphabeticallyCheck;
private Button sortCaseInsensitiveCheck;
private Button sortFoldersFirstCheck;
private Button showConnectionHostCheck;
@@ -156,13 +158,26 @@ public class PrefPageDatabaseNavigator extends AbstractPrefPage implements IWork
// TODO: remove or enable this setting
groupByDriverCheck.setEnabled(false);
sortCaseInsensitiveCheck = UIUtils.createCheckbox(
sortAlphabeticallyCheck = UIUtils.createCheckbox(
navigatorGroup,
UINavigatorMessages.pref_page_database_general_label_order_elements_alphabetically,
UINavigatorMessages.pref_page_database_general_label_order_elements_alphabetically_tip,
false,
2
);
sortCaseInsensitiveCheck = UIUtils.createCheckbox(
navigatorGroup,
UINavigatorMessages.pref_page_database_general_label_sort_case_insensitive,
UINavigatorMessages.pref_page_database_general_label_sort_case_insensitive_tip,
false,
2
);
sortAlphabeticallyCheck.addSelectionListener(
SelectionListener.widgetSelectedAdapter(e -> {
boolean isAlphabetical = sortAlphabeticallyCheck.getSelection();
sortCaseInsensitiveCheck.setSelection(isAlphabetical);
sortCaseInsensitiveCheck.setEnabled(isAlphabetical);
}));
colorAllNodesCheck = UIUtils.createCheckbox(
navigatorGroup,
@@ -302,11 +317,18 @@ public class PrefPageDatabaseNavigator extends AbstractPrefPage implements IWork
? store.getDefaultBoolean(NavigatorPreferences.NAVIGATOR_GROUP_BY_DRIVER)
: store.getBoolean(NavigatorPreferences.NAVIGATOR_GROUP_BY_DRIVER)
);
sortCaseInsensitiveCheck.setSelection(
sortAlphabeticallyCheck.setSelection(
useDefaultValues
? store.getDefaultBoolean(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY)
: store.getBoolean(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY)
);
sortCaseInsensitiveCheck.setSelection(
useDefaultValues
? store.getDefaultBoolean(ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE)
: store.getBoolean(ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE)
);
sortCaseInsensitiveCheck.setEnabled(sortAlphabeticallyCheck.getSelection());
colorAllNodesCheck.setSelection(
useDefaultValues
? store.getDefaultBoolean(NavigatorPreferences.NAVIGATOR_COLOR_ALL_NODES)
@@ -401,7 +423,8 @@ public class PrefPageDatabaseNavigator extends AbstractPrefPage implements IWork
store.setValue(NavigatorPreferences.NAVIGATOR_SHOW_TOOLTIPS, showToolTipsCheck.getSelection());
store.setValue(NavigatorPreferences.NAVIGATOR_SHOW_CONTENTS_IN_TOOLTIP, showContentsInToolTipsContents.getSelection());
store.setValue(NavigatorPreferences.NAVIGATOR_EDITOR_SHOW_TABLE_GRID, showTableGrid.getSelection());
store.setValue(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, sortCaseInsensitiveCheck.getSelection());
store.setValue(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, sortAlphabeticallyCheck.getSelection());
store.setValue(ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE, sortCaseInsensitiveCheck.getSelection());
store.setValue(ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST, sortFoldersFirstCheck.getSelection());
store.setValue(NavigatorPreferences.NAVIGATOR_SHOW_CHILD_COUNT, showChildCountCheck.getSelection());
store.setValue(NavigatorPreferences.NAVIGATOR_SHOW_CONNECTION_HOST_NAME, showConnectionHostCheck.getSelection());

View File

@@ -0,0 +1,16 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: DBeaver Navigator Tests
Bundle-SymbolicName: org.jkiss.dbeaver.model.navigator.test
Bundle-Version: 1.0.0.qualifier
Bundle-Release-Date: 20251006
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-Vendor: DBeaver Corp
Fragment-Host: org.jkiss.dbeaver.model
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
org.junit,
org.mockito.mockito-core,
org.jkiss.dbeaver.test.platform,
org.jkiss.dbeaver.model

View File

@@ -0,0 +1,5 @@
source..=src/
output..=target/classes/
bin.includes=.,\
META-INF/
.

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ DBeaver - Universal Database Manager
~ Copyright (C) 2010-2024 DBeaver Corp and others
~
~ 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.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jkiss.dbeaver</groupId>
<artifactId>tests</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<artifactId>org.jkiss.dbeaver.model.navigator.test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
</project>

View File

@@ -0,0 +1,138 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
*
* 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.jkiss.dbeaver.model.navigator;
import org.jkiss.dbeaver.ModelPreferences;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.junit.DBeaverUnitTest;
import org.junit.After;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.*;
public class DBNUtilsTest extends DBeaverUnitTest {
private final List<String> changedProperties = new ArrayList<>();
@After
public void tearDown() {
var prefStore = DBWorkbench.getPlatform().getPreferenceStore();
changedProperties.forEach(prefStore::setToDefault);
changedProperties.clear();
}
@Test
public void shouldNotSortByNameIfAlphabeticallyIfAlphabeticallyFalse() {
// given
addProperty(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, false);
addProperty(ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST, false);
//then
assertRemainUnsorted();
}
@Test
public void shouldNotSortByNameIfAlphabeticallyFalseAndByFolderTrue() {
// given
addProperty(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, false);
addProperty(ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST, true);
//then
assertRemainUnsorted();
}
@Test
public void shouldSortIgnoreCaseWhenIgnoreCaseTrue(){
// given
addProperty(ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE, true);
//then
assertCorrectSortingIgnoreCase(true);
assertCorrectSortingIgnoreCase(false);
}
@Test
public void shouldSortWithCaseWhenIgnoreCaseFalse(){
// given
addProperty(ModelPreferences.NAVIGATOR_SORT_IGNORE_CASE, false);
//then
assertCorrectSortingWithCase(true);
assertCorrectSortingWithCase(false);
}
private void assertRemainUnsorted() {
List<String> givenNames = List.of("b", "a", "A", "C");
List<String> expectedNames = List.of("b", "a", "A", "C");
// when
var result = DBNUtils.filterNavigableChildren(getNamedNodes(givenNames), true);
// then
assertEquals(expectedNames, Arrays.stream(result).map(DBNNode::getNodeDisplayName).toList());
}
private void assertCorrectSortingIgnoreCase(boolean isFoldersFirst) {
addProperty(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, true);
addProperty(ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST, isFoldersFirst);
assertCorrectSortingIgnoreCase(List.of("a", "A", "b", "C"), List.of("b", "a", "A", "C"));
assertCorrectSortingIgnoreCase(List.of("s1", "s2", "s03", "s10"), List.of("s2", "s1", "s10", "s03"));
assertCorrectSortingIgnoreCase(List.of("s1123456789123456789", "s2123456789123456789"), List.of("s2123456789123456789", "s1123456789123456789"));
}
private void assertCorrectSortingWithCase(boolean isFoldersFirst) {
addProperty(ModelPreferences.NAVIGATOR_SORT_ALPHABETICALLY, true);
addProperty(ModelPreferences.NAVIGATOR_SORT_FOLDERS_FIRST, isFoldersFirst);
assertCorrectSortingIgnoreCase(List.of("A", "C", "a", "b"), List.of("b", "a", "A", "C"));
assertCorrectSortingIgnoreCase(List.of("s1", "s2", "s03", "s10"), List.of("s2", "s1", "s10", "s03"));
assertCorrectSortingIgnoreCase(
List.of("s1123456789123456789", "s2123456789123456789"),
List.of("s2123456789123456789", "s1123456789123456789")
);
}
private void assertCorrectSortingIgnoreCase(List<String> expectedNames, List<String> givenNames) {
var result = DBNUtils.filterNavigableChildren(getNamedNodes(givenNames), true);
// then
assertEquals(expectedNames, Arrays.stream(result).map(DBNNode::getNodeDisplayName).toList());
}
private void addProperty(String key, boolean value) {
var prefStore = DBWorkbench.getPlatform().getPreferenceStore();
if (!prefStore.contains(key)) {
throw new IllegalArgumentException("No such property: " + key);
}
changedProperties.add(key);
prefStore.setValue(key, value);
}
private DBNNode[] getNamedNodes(List<String> names) {
return names
.stream()
.map(this::createMockNamedNode)
.toArray(DBNNode[]::new);
}
private DBNNode createMockNamedNode(String name) {
DBNNode node = mock(DBNNode.class, RETURNS_DEEP_STUBS);
when(node.getNodeDisplayName()).thenReturn(name);
return node;
}
}

View File

@@ -18,60 +18,46 @@ package org.jkiss.util;
import org.jkiss.code.NotNull;
import org.jkiss.utils.AlphanumericComparator;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class AlphanumericComparatorTest {
private final AlphanumericComparator comparator = AlphanumericComparator.getInstance();
@Test
public void alphanumericComparatorTest() {
alphanumericComparatorTestImpl(
List.of("img12", "img10", "img2", "img1", "img100_1", "img100_11", "img100", "img100_10", "img100_5"),
List.of("img1", "img2", "img10", "img12", "img100", "img100_1", "img100_5", "img100_10", "img100_11")
);
public void testAlphanumericComparator() {
assertComparatorLowercaseCasesPass(comparator);
}
alphanumericComparatorTestImpl(
List.of("file1000", "file100", "file10", "file2", "file1", "file11", "file200", "file20", "file2a", "file2b"),
List.of("file1", "file2", "file2a", "file2b", "file10", "file11", "file20", "file100", "file200", "file1000")
);
@Test
public void testAlphanumericComparatorIgnoreCaseTestInsensitive() {
assertComparatorLowercaseCasesPass(comparator::compareIgnoreCase);
}
alphanumericComparatorTestImpl(
List.of("doc10", "doc2", "doc20", "doc1", "doc3", "doc15", "doc4"),
List.of("doc1", "doc2", "doc3", "doc4", "doc10", "doc15", "doc20")
);
@Test
public void comparatorIgnoreCaseTestBorderCases() {
AlphanumericComparator alphanumericComparator = AlphanumericComparator.getInstance();
// even cases letters
assertEquals(0, alphanumericComparator.compareIgnoreCase("A", "A"));
assertEquals(0, alphanumericComparator.compareIgnoreCase("a", "A"));
assertEquals(0, alphanumericComparator.compareIgnoreCase("a", "a"));
assertEquals(0, alphanumericComparator.compareIgnoreCase("test", "TEST"));
assertEquals(0, alphanumericComparator.compareIgnoreCase("TesT", "TEst"));
assertEquals(0, alphanumericComparator.compareIgnoreCase("TesT", "TEst"));
assertEquals(0, alphanumericComparator.compareIgnoreCase("LongStringWithCASE", "longstringwithcase"));
alphanumericComparatorTestImpl(
List.of("page2", "page12", "page3", "page22", "page4", "page13", "page23"),
List.of("page2", "page3", "page4", "page12", "page13", "page22", "page23")
);
alphanumericComparatorTestImpl(
List.of("item-5", "item-1", "item-10", "item-2", "item-11", "item-3", "item-20", "item-15"),
List.of("item-1", "item-2", "item-3", "item-5", "item-10", "item-11", "item-15", "item-20")
);
alphanumericComparatorTestImpl(
List.of("abc123def45", "abc12def345", "abc1234def5", "abc12345def4", "abc1234def45", "abc12345def456"),
List.of("abc12def345", "abc123def45", "abc1234def5", "abc1234def45", "abc12345def4", "abc12345def456")
);
alphanumericComparatorTestImpl(
List.of("file01_v2", "file02_v1", "file10_v10", "file02_v10", "file10_v2", "file1_v10"),
List.of("file01_v2", "file1_v10", "file02_v1", "file02_v10", "file10_v2", "file10_v10")
);
alphanumericComparatorTestImpl(
List.of("chapter-2.1.1", "chapter-10.1.1", "chapter-2.1.10", "chapter-10.1.2", "chapter-2.1.2"),
List.of("chapter-2.1.1", "chapter-2.1.2", "chapter-2.1.10", "chapter-10.1.1", "chapter-10.1.2")
);
alphanumericComparatorTestImpl(
List.of("item_1_2_3", "item_2_1_3", "item_1_10_3", "item_2_2_1", "item_1_2_10", "item_2_1_10", "item_1_10_1"),
List.of("item_1_2_3", "item_1_2_10", "item_1_10_1", "item_1_10_3", "item_2_1_3", "item_2_1_10", "item_2_2_1")
);
// not even
assertTrue(alphanumericComparator.compareIgnoreCase("b", "a") > 0);
assertTrue(alphanumericComparator.compareIgnoreCase("b", "A") > 0);
assertTrue(alphanumericComparator.compareIgnoreCase("a2", "A1") > 0);
assertTrue(alphanumericComparator.compareIgnoreCase("aa", "a") > 0);
}
@Test
@@ -280,16 +266,276 @@ public class AlphanumericComparatorTest {
"tb_2024062809552812364500_c"
);
alphanumericComparatorTestImpl(input, expected);
assertComparatorSortingMatches(input, expected, comparator);
}
private void alphanumericComparatorTestImpl(
@Test
public void comparatorIgnoreCaseContractTest() {
var input = List.of(
"tb_2024062717021917181100_a",
"tb_2024062717021917181100_b",
"tb_2024062717021917181100_c",
"tb_2024062717021987321300_a",
"tb_2024062717021987321300_b",
"tb_2024062717021987321300_c",
"tb_2024062717025873983900_a",
"tb_2024062717025873983900_b",
"tb_2024062717025873983900_c",
"tb_2024062717025946972500_a",
"tb_2024062717025946972500_b",
"tb_2024062717025946972500_c",
"tb_2024062808443487429400_a",
"tb_2024062808443487429400_b",
"tb_2024062808443487429400_c",
"tb_2024062808443565182500_a",
"tb_2024062808443565182500_b",
"tb_2024062808443565182500_c",
"tb_2024062808485852240700_a",
"tb_2024062808485852240700_b",
"tb_2024062808485852240700_c",
"tb_2024062808485922846100_a",
"tb_2024062808485922846100_b",
"tb_2024062808485922846100_c",
"tb_2024062808510343420400_a",
"tb_2024062808510343420400_b",
"tb_2024062808510343420400_c",
"tb_2024062808510415832700_a",
"tb_2024062808510415832700_b",
"tb_2024062808510415832700_c",
"tb_2024062808555338721800_a",
"tb_2024062808555338721800_b",
"tb_2024062808555338721800_c",
"tb_2024062808555413504500_a",
"tb_2024062808555413504500_b",
"tb_2024062808555413504500_c",
"tb_2024062809004817546200_a",
"tb_2024062809004817546200_b",
"tb_2024062809004817546200_c",
"tb_2024062809004891493500_a",
"tb_2024062809004891493500_b",
"tb_2024062809004891493500_c",
"tb_2024062809072784889600_a",
"tb_2024062809072784889600_b",
"tb_2024062809072784889600_c",
"tb_2024062809072838776600_a",
"tb_2024062809072838776600_b",
"tb_2024062809072838776600_c",
"tb_2024062809072959260600_a",
"tb_2024062809072959260600_b",
"tb_2024062809072959260600_c",
"tb_2024062809110749009200_a",
"tb_2024062809110749009200_b",
"tb_2024062809110749009200_c",
"tb_2024062809110795555700_a",
"tb_2024062809110795555700_b",
"tb_2024062809110795555700_c",
"tb_2024062809110913591500_a",
"tb_2024062809110913591500_b",
"tb_2024062809110913591500_c",
"tb_2024062809172348494500_a",
"tb_2024062809172348494500_b",
"tb_2024062809172348494500_c",
"tb_2024062809172394170600_a",
"tb_2024062809172394170600_b",
"tb_2024062809172394170600_c",
"tb_2024062809172530677400_a",
"tb_2024062809172530677400_b",
"tb_2024062809172530677400_c",
"tb_2024062809260991490600_a",
"tb_2024062809260991490600_b",
"tb_2024062809260991490600_c",
"tb_202406280926103824900_a",
"tb_202406280926103824900_b",
"tb_202406280926103824900_c",
"tb_2024062809261166102200_a",
"tb_2024062809261166102200_b",
"tb_2024062809261166102200_c",
"tb_2024062809271296363100_a",
"tb_2024062809271296363100_b",
"tb_2024062809271296363100_c",
"tb_2024062809271342741900_a",
"tb_2024062809271342741900_b",
"tb_2024062809271342741900_c",
"tb_2024062809271471046200_a",
"tb_2024062809271471046200_b",
"tb_2024062809271471046200_c",
"tb_2024062809504349285400_a",
"tb_2024062809504349285400_b",
"tb_2024062809504349285400_c",
"tb_2024062809504414294300_a",
"tb_2024062809504414294300_b",
"tb_2024062809504414294300_c",
"tb_2024062809504557202400_a",
"tb_2024062809504557202400_b",
"tb_2024062809504557202400_c",
"tb_2024062809552812364500_a",
"tb_2024062809552812364500_b",
"tb_2024062809552812364500_c"
);
var expected = List.of(
"tb_202406280926103824900_a",
"tb_202406280926103824900_b",
"tb_202406280926103824900_c",
"tb_2024062717021917181100_a",
"tb_2024062717021917181100_b",
"tb_2024062717021917181100_c",
"tb_2024062717021987321300_a",
"tb_2024062717021987321300_b",
"tb_2024062717021987321300_c",
"tb_2024062717025873983900_a",
"tb_2024062717025873983900_b",
"tb_2024062717025873983900_c",
"tb_2024062717025946972500_a",
"tb_2024062717025946972500_b",
"tb_2024062717025946972500_c",
"tb_2024062808443487429400_a",
"tb_2024062808443487429400_b",
"tb_2024062808443487429400_c",
"tb_2024062808443565182500_a",
"tb_2024062808443565182500_b",
"tb_2024062808443565182500_c",
"tb_2024062808485852240700_a",
"tb_2024062808485852240700_b",
"tb_2024062808485852240700_c",
"tb_2024062808485922846100_a",
"tb_2024062808485922846100_b",
"tb_2024062808485922846100_c",
"tb_2024062808510343420400_a",
"tb_2024062808510343420400_b",
"tb_2024062808510343420400_c",
"tb_2024062808510415832700_a",
"tb_2024062808510415832700_b",
"tb_2024062808510415832700_c",
"tb_2024062808555338721800_a",
"tb_2024062808555338721800_b",
"tb_2024062808555338721800_c",
"tb_2024062808555413504500_a",
"tb_2024062808555413504500_b",
"tb_2024062808555413504500_c",
"tb_2024062809004817546200_a",
"tb_2024062809004817546200_b",
"tb_2024062809004817546200_c",
"tb_2024062809004891493500_a",
"tb_2024062809004891493500_b",
"tb_2024062809004891493500_c",
"tb_2024062809072784889600_a",
"tb_2024062809072784889600_b",
"tb_2024062809072784889600_c",
"tb_2024062809072838776600_a",
"tb_2024062809072838776600_b",
"tb_2024062809072838776600_c",
"tb_2024062809072959260600_a",
"tb_2024062809072959260600_b",
"tb_2024062809072959260600_c",
"tb_2024062809110749009200_a",
"tb_2024062809110749009200_b",
"tb_2024062809110749009200_c",
"tb_2024062809110795555700_a",
"tb_2024062809110795555700_b",
"tb_2024062809110795555700_c",
"tb_2024062809110913591500_a",
"tb_2024062809110913591500_b",
"tb_2024062809110913591500_c",
"tb_2024062809172348494500_a",
"tb_2024062809172348494500_b",
"tb_2024062809172348494500_c",
"tb_2024062809172394170600_a",
"tb_2024062809172394170600_b",
"tb_2024062809172394170600_c",
"tb_2024062809172530677400_a",
"tb_2024062809172530677400_b",
"tb_2024062809172530677400_c",
"tb_2024062809260991490600_a",
"tb_2024062809260991490600_b",
"tb_2024062809260991490600_c",
"tb_2024062809261166102200_a",
"tb_2024062809261166102200_b",
"tb_2024062809261166102200_c",
"tb_2024062809271296363100_a",
"tb_2024062809271296363100_b",
"tb_2024062809271296363100_c",
"tb_2024062809271342741900_a",
"tb_2024062809271342741900_b",
"tb_2024062809271342741900_c",
"tb_2024062809271471046200_a",
"tb_2024062809271471046200_b",
"tb_2024062809271471046200_c",
"tb_2024062809504349285400_a",
"tb_2024062809504349285400_b",
"tb_2024062809504349285400_c",
"tb_2024062809504414294300_a",
"tb_2024062809504414294300_b",
"tb_2024062809504414294300_c",
"tb_2024062809504557202400_a",
"tb_2024062809504557202400_b",
"tb_2024062809504557202400_c",
"tb_2024062809552812364500_a",
"tb_2024062809552812364500_b",
"tb_2024062809552812364500_c"
);
assertComparatorSortingMatches(input, expected, comparator::compareIgnoreCase);
}
private void assertComparatorLowercaseCasesPass(@NotNull Comparator<? super CharSequence> comparator) {
assertComparatorSortingMatches(
List.of("img12", "img10", "img2", "img1", "img100_1", "img100_11", "img100", "img100_10", "img100_5"),
List.of("img1", "img2", "img10", "img12", "img100", "img100_1", "img100_5", "img100_10", "img100_11"),
comparator
);
assertComparatorSortingMatches(
List.of("file1000", "file100", "file10", "file2", "file1", "file11", "file200", "file20", "file2a", "file2b"),
List.of("file1", "file2", "file2a", "file2b", "file10", "file11", "file20", "file100", "file200", "file1000"),
comparator
);
assertComparatorSortingMatches(
List.of("doc10", "doc2", "doc20", "doc1", "doc3", "doc15", "doc4"),
List.of("doc1", "doc2", "doc3", "doc4", "doc10", "doc15", "doc20"),
comparator
);
assertComparatorSortingMatches(
List.of("page2", "page12", "page3", "page22", "page4", "page13", "page23"),
List.of("page2", "page3", "page4", "page12", "page13", "page22", "page23"),
comparator
);
assertComparatorSortingMatches(
List.of("item-5", "item-1", "item-10", "item-2", "item-11", "item-3", "item-20", "item-15"),
List.of("item-1", "item-2", "item-3", "item-5", "item-10", "item-11", "item-15", "item-20"),
comparator
);
assertComparatorSortingMatches(
List.of("abc123def45", "abc12def345", "abc1234def5", "abc12345def4", "abc1234def45", "abc12345def456"),
List.of("abc12def345", "abc123def45", "abc1234def5", "abc1234def45", "abc12345def4", "abc12345def456"),
comparator
);
assertComparatorSortingMatches(
List.of("file01_v2", "file02_v1", "file10_v10", "file02_v10", "file10_v2", "file1_v10"),
List.of("file01_v2", "file1_v10", "file02_v1", "file02_v10", "file10_v2", "file10_v10"),
comparator
);
assertComparatorSortingMatches(
List.of("chapter-2.1.1", "chapter-10.1.1", "chapter-2.1.10", "chapter-10.1.2", "chapter-2.1.2"),
List.of("chapter-2.1.1", "chapter-2.1.2", "chapter-2.1.10", "chapter-10.1.1", "chapter-10.1.2"),
comparator
);
assertComparatorSortingMatches(
List.of("item_1_2_3", "item_2_1_3", "item_1_10_3", "item_2_2_1", "item_1_2_10", "item_2_1_10", "item_1_10_1"),
List.of("item_1_2_3", "item_1_2_10", "item_1_10_1", "item_1_10_3", "item_2_1_3", "item_2_1_10", "item_2_2_1"),
comparator
);
}
private void assertComparatorSortingMatches(
@NotNull Collection<? extends CharSequence> input,
@NotNull Collection<? extends CharSequence> expected
@NotNull Collection<? extends CharSequence> expected,
@NotNull Comparator<? super CharSequence> comparator
) {
final ArrayList<? extends CharSequence> sorted = new ArrayList<>(input);
sorted.sort(AlphanumericComparator.getInstance());
sorted.sort(comparator);
Assert.assertEquals(expected, sorted);
assertEquals(expected, sorted);
}
}

View File

@@ -26,6 +26,7 @@
<module>org.jkiss.dbeaver.ext.snowflake.test</module>
<module>org.jkiss.dbeaver.ext.sqlite.test</module>
<module>org.jkiss.dbeaver.model.lsm.test</module>
<module>org.jkiss.dbeaver.model.navigator.test</module>
<module>org.jkiss.dbeaver.model.ai.test</module>
</modules>