mirror of
https://github.com/nextcloud/android.git
synced 2024-11-22 21:25:35 +03:00
Merge pull request #1804 from nextcloud/newSorting
new sorting, adapted to server
This commit is contained in:
commit
c52e33ab9d
3 changed files with 183 additions and 47 deletions
|
@ -1,2 +1,2 @@
|
|||
DO NOT TOUCH; GENERATED BY DRONE
|
||||
<span class="mdl-layout-title">Lint Report: 445 warnings</span>
|
||||
<span class="mdl-layout-title">Lint Report: 444 warnings</span>
|
||||
|
|
|
@ -23,55 +23,59 @@
|
|||
*/
|
||||
|
||||
package third_parties.daveKoeller;
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
|
||||
/**
|
||||
* This is an updated version with enhancements made by Daniel Migowski,
|
||||
* Andre Bogus, and David Koelle
|
||||
*
|
||||
import java.io.File;
|
||||
import java.text.Collator;
|
||||
import java.util.Comparator;
|
||||
|
||||
/*
|
||||
* This is an updated version with enhancements made by Daniel Migowski, Andre Bogus, and David Koelle
|
||||
* *
|
||||
* To convert to use Templates (Java 1.5+):
|
||||
* - Change "implements Comparator" to "implements Comparator<String>"
|
||||
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
|
||||
* - Remove the type checking and casting in compare().
|
||||
*
|
||||
* - Change "implements Comparator" to "implements Comparator<String>"
|
||||
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
|
||||
* - Remove the type checking and casting in compare().
|
||||
*
|
||||
* To use this class:
|
||||
* Use the static "sort" method from the java.util.Collections class:
|
||||
* Collections.sort(your list, new AlphanumComparator());
|
||||
* Use the static "sort" method from the java.util.Collections class:
|
||||
* Collections.sort(your list, new AlphanumComparator());
|
||||
*
|
||||
* Adapted to fit
|
||||
* https://github.com/nextcloud/server/blob/9a4253ef7c34f9dc71a6a9f7828a10df769f0c32/tests/lib/NaturalSortTest.php
|
||||
* by Tobias Kaminsky
|
||||
*/
|
||||
public class AlphanumComparator implements Comparator<OCFile>
|
||||
{
|
||||
private final boolean isDigit(char ch)
|
||||
{
|
||||
public class AlphanumComparator<T> implements Comparator<T> {
|
||||
private boolean isDigit(char ch) {
|
||||
return ch >= 48 && ch <= 57;
|
||||
}
|
||||
|
||||
/** Length of string is passed in for improved efficiency (only need to calculate it once) **/
|
||||
private final String getChunk(String s, int slength, int marker)
|
||||
{
|
||||
private boolean isSpecialChar(char ch) {
|
||||
return ch <= 47 || ch >= 58 && ch <= 64 || ch >= 91 && ch <= 96 || ch >= 123 && ch <= 126;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of string is passed in for improved efficiency (only need to calculate it once)
|
||||
**/
|
||||
private String getChunk(String string, int stringLength, int marker) {
|
||||
StringBuilder chunk = new StringBuilder();
|
||||
char c = s.charAt(marker);
|
||||
char c = string.charAt(marker);
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
if (isDigit(c))
|
||||
{
|
||||
while (marker < slength)
|
||||
{
|
||||
c = s.charAt(marker);
|
||||
if (isDigit(c)) {
|
||||
while (marker < stringLength) {
|
||||
c = string.charAt(marker);
|
||||
if (!isDigit(c)) {
|
||||
break;
|
||||
}
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
while (marker < slength)
|
||||
{
|
||||
c = s.charAt(marker);
|
||||
if (isDigit(c)) {
|
||||
} else if (!isSpecialChar(c)) {
|
||||
while (marker < stringLength) {
|
||||
c = string.charAt(marker);
|
||||
if (isDigit(c) || isSpecialChar(c)) {
|
||||
break;
|
||||
}
|
||||
chunk.append(c);
|
||||
|
@ -81,28 +85,31 @@ public class AlphanumComparator implements Comparator<OCFile>
|
|||
return chunk.toString();
|
||||
}
|
||||
|
||||
public int compare(OCFile o1, OCFile o2){
|
||||
public int compare(OCFile o1, OCFile o2) {
|
||||
String s1 = o1.getRemotePath().toLowerCase();
|
||||
String s2 = o2.getRemotePath().toLowerCase();
|
||||
|
||||
return compare(s1, s2);
|
||||
}
|
||||
|
||||
public int compare(File f1, File f2){
|
||||
public int compare(File f1, File f2) {
|
||||
String s1 = f1.getPath().toLowerCase();
|
||||
String s2 = f2.getPath().toLowerCase();
|
||||
|
||||
return compare(s1, s2);
|
||||
}
|
||||
|
||||
public int compare(T t1, T t2) {
|
||||
return compare(t1.toString(), t2.toString());
|
||||
}
|
||||
|
||||
public int compare(String s1, String s2) {
|
||||
int thisMarker = 0;
|
||||
int thatMarker = 0;
|
||||
int s1Length = s1.length();
|
||||
int s2Length = s2.length();
|
||||
|
||||
while (thisMarker < s1Length && thatMarker < s2Length)
|
||||
{
|
||||
while (thisMarker < s1Length && thatMarker < s2Length) {
|
||||
String thisChunk = getChunk(s1, s1Length, thisMarker);
|
||||
thisMarker += thisChunk.length();
|
||||
|
||||
|
@ -111,26 +118,38 @@ public class AlphanumComparator implements Comparator<OCFile>
|
|||
|
||||
// If both chunks contain numeric characters, sort them numerically
|
||||
int result = 0;
|
||||
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
|
||||
{
|
||||
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
|
||||
// Simple chunk comparison by length.
|
||||
int thisChunkLength = thisChunk.length();
|
||||
result = thisChunkLength - thatChunk.length();
|
||||
// If equal, the first different number counts
|
||||
if (result == 0)
|
||||
{
|
||||
for (int i = 0; i < thisChunkLength; i++)
|
||||
{
|
||||
if (result == 0) {
|
||||
for (int i = 0; i < thisChunkLength; i++) {
|
||||
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
||||
if (result != 0)
|
||||
{
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = thisChunk.compareTo(thatChunk);
|
||||
} else if (isSpecialChar(thisChunk.charAt(0)) && isSpecialChar(thatChunk.charAt(0))) {
|
||||
for (int i = 0; i < thisChunk.length(); i++) {
|
||||
if (thisChunk.charAt(i) == '.') {
|
||||
return -1;
|
||||
} else if (thatChunk.charAt(i) == '.') {
|
||||
return 1;
|
||||
} else {
|
||||
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isSpecialChar(thisChunk.charAt(0)) && !isSpecialChar(thatChunk.charAt(0))) {
|
||||
return -1;
|
||||
} else if (!isSpecialChar(thisChunk.charAt(0)) && isSpecialChar(thatChunk.charAt(0))) {
|
||||
return 1;
|
||||
} else {
|
||||
result = Collator.getInstance().compare(thisChunk, thatChunk);
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
|
|
117
src/test/java/com/owncloud/android/utils/TestSorting.java
Normal file
117
src/test/java/com/owncloud/android/utils/TestSorting.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
package com.owncloud.android.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import third_parties.daveKoeller.AlphanumComparator;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2017 Tobias Kaminsky
|
||||
* Copyright (C) 2017 Nextcloud GmbH.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Tests used from
|
||||
https://github.com/nextcloud/server/blob/9a4253ef7c34f9dc71a6a9f7828a10df769f0c32/tests/lib/NaturalSortTest.php
|
||||
at 2017-11-21 to stay in sync with server.
|
||||
Added first test with special chars
|
||||
*/
|
||||
|
||||
public class TestSorting {
|
||||
|
||||
@Test
|
||||
public void testSpecialChars() {
|
||||
|
||||
String[] unsortedArray = {"11 - November", "Test 04", "Test 01", "Ôle", "Üüü", "01 - Januar", "[Test] Folder",
|
||||
"z.[Test]", "z. Test"};
|
||||
|
||||
String[] sortedArray = {"[Test] Folder", "01 - Januar", "11 - November", "Ôle", "Test 01", "Test 04", "Üüü",
|
||||
"z. Test", "z.[Test]"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifferentCasing() {
|
||||
String[] unsortedArray = {"aaa", "bbb", "BBB", "AAA"};
|
||||
String[] sortedArray = {"aaa", "AAA", "bbb", "BBB"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumbers() {
|
||||
String[] unsortedArray = {"124.txt", "abc1", "123.txt", "abc", "abc2", "def (2).txt", "ghi 10.txt", "abc12",
|
||||
"def.txt", "def (1).txt", "ghi 2.txt", "def (10).txt", "abc10", "def (12).txt", "z", "ghi.txt", "za",
|
||||
"ghi 1.txt", "ghi 12.txt", "zz", "15.txt", "15b.txt"};
|
||||
|
||||
String[] sortedArray = {"15.txt", "15b.txt", "123.txt", "124.txt", "abc", "abc1", "abc2", "abc10", "abc12",
|
||||
"def.txt", "def (1).txt", "def (2).txt", "def (10).txt", "def (12).txt", "ghi.txt", "ghi 1.txt",
|
||||
"ghi 2.txt", "ghi 10.txt", "ghi 12.txt", "z", "za", "zz"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChineseCharacters() {
|
||||
String[] unsortedArray = {"十.txt", "一.txt", "二.txt", "十 2.txt", "三.txt", "四.txt", "abc.txt", "五.txt",
|
||||
"七.txt", "八.txt", "九.txt", "六.txt", "十一.txt", "波.txt", "破.txt", "莫.txt", "啊.txt", "123.txt"};
|
||||
|
||||
String[] sortedArray = {"123.txt", "abc.txt", "一.txt", "七.txt", "三.txt", "九.txt", "二.txt", "五.txt",
|
||||
"八.txt", "六.txt", "十.txt", "十 2.txt", "十一.txt", "啊.txt", "四.txt", "波.txt", "破.txt", "莫.txt"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUmlauts() {
|
||||
String[] unsortedArray = {"öh.txt", "Äh.txt", "oh.txt", "Üh 2.txt", "Üh.txt", "ah.txt", "Öh.txt", "uh.txt",
|
||||
"üh.txt", "äh.txt"};
|
||||
String[] sortedArray = {"ah.txt", "äh.txt", "Äh.txt", "oh.txt", "öh.txt", "Öh.txt", "uh.txt", "üh.txt",
|
||||
"Üh.txt", "Üh 2.txt"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
private boolean sortAndTest(String[] unsortedArray, String[] sortedArray) {
|
||||
List<String> unsortedList = Arrays.asList(unsortedArray);
|
||||
List<String> sortedList = Arrays.asList(sortedArray);
|
||||
|
||||
|
||||
Collections.sort(unsortedList, new AlphanumComparator());
|
||||
|
||||
for (int i = 0; i < sortedList.size(); i++) {
|
||||
if (sortedList.get(i).compareTo(unsortedList.get(i)) != 0) {
|
||||
|
||||
System.out.println(" target: " + sortedList.toString());
|
||||
System.out.println(" actual: " + unsortedList.toString());
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue