[Git][java-team/libsejda-commons-java][upstream] New upstream version 1.1.6

Markus Koschany gitlab at salsa.debian.org
Sat Jan 30 23:39:15 GMT 2021



Markus Koschany pushed to branch upstream at Debian Java Maintainers / libsejda-commons-java


Commits:
3d141f3c by Markus Koschany at 2021-01-31T00:32:56+01:00
New upstream version 1.1.6
- - - - -


3 changed files:

- pom.xml
- src/main/java/org/sejda/commons/util/NumericalSortFilenameComparator.java
- src/test/java/org/sejda/commons/util/NumericalSortFilenameComparatorTest.java


Changes:

=====================================
pom.xml
=====================================
@@ -5,7 +5,7 @@
 	<artifactId>sejda-commons</artifactId>
 	<packaging>jar</packaging>
 	<name>sejda-commons</name>
-	<version>1.1.4</version>
+	<version>1.1.6</version>
 
 	<description>A collection of utilities and common classes.</description>
 	<url>http://www.sejda.org</url>
@@ -37,7 +37,7 @@
 		<connection>scm:git:git at github.com:torakiki/sejda-commons.git</connection>
 		<developerConnection>scm:git:git at github.com:torakiki/sejda-commons.git</developerConnection>
 		<url>scm:git:git at github.com:torakiki/sejda-commons.git</url>
-		<tag>v1.1.4</tag>
+		<tag>v1.1.6</tag>
 	</scm>
 
 	<developers>


=====================================
src/main/java/org/sejda/commons/util/NumericalSortFilenameComparator.java
=====================================
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 Sober Lemur S.a.s. di Vacondio Andrea and Sejda BV
+ * Copyright 2018 Sober Lemur S.a.s. di Vacondio Andrea and Sejda BV
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,51 +15,104 @@
  */
 package org.sejda.commons.util;
 
+import static java.util.Comparator.comparing;
+import static java.util.Comparator.nullsLast;
 import static java.util.Objects.nonNull;
+import static java.util.Optional.ofNullable;
+import static org.sejda.commons.util.StringUtils.isEmpty;
+import static org.sejda.commons.util.StringUtils.isNotEmpty;
 
 import java.io.File;
 import java.math.BigInteger;
 import java.util.Comparator;
-import java.util.Optional;
 import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
- * Comparator for filenames that performs a numerical sort if the file names start with digits, returns 0 in any other case.
+ * Comparator for filenames that performs a numerical sort if the file names start or end with digits. It allows to specify a fallback comparator to use in case the numerical sort
+ * fails. The goal is to behave as close as possible to file managers sorting results.
  * 
  * @author Andrea Vacondio
  *
  */
 public class NumericalSortFilenameComparator implements Comparator<File> {
 
-    public static Logger LOG = LoggerFactory.getLogger(NumericalSortFilenameComparator.class);
-    private Pattern pattern = Pattern.compile("^(\\d*)(.*)$");
+    private static Pattern PATTERN = Pattern.compile("^(\\d*)(\\D*)(\\d*)$");
+
+    private static Function<String, BigInteger> DIGITS_EXTRACTOR = (g) -> {
+        return ofNullable(g).filter(StringUtils::isNotEmpty).map(BigInteger::new).orElse(null);
+    };
+
+    private static Comparator<String> BIG_INT_COMPARATOR = (a, b) -> {
+        BigInteger bigA = DIGITS_EXTRACTOR.apply(a);
+        BigInteger bigB = DIGITS_EXTRACTOR.apply(b);
+        if (nonNull(bigA) && nonNull(bigB)) {
+            return bigA.compareTo(bigB);
+        }
+        return 0;
+    };
 
-    private Function<File, BigInteger> leadingDigits = (f) -> {
-        if (nonNull(f)) {
-            Matcher matcher = pattern.matcher(f.getName().toLowerCase());
-            if (matcher.matches()) {
-                return Optional.of(matcher.group(1)).filter(StringUtils::isNotEmpty).map(BigInteger::new).orElse(null);
+    private static Comparator<String> STRING_COMPARATOR = (a, b) -> {
+        if (isNotEmpty(a) && isNotEmpty(b)) {
+            return a.compareToIgnoreCase(b);
+        }
+        return 0;
+    };
+
+    private static String basename(File file) {
+        if (nonNull(file)) {
+            String filename = file.getName();
+            int index = filename.lastIndexOf('.');
+            if (index > 0) {
+                return filename.substring(0, index);
+            }
+            if (StringUtils.isNotEmpty(filename)) {
+                return filename;
             }
         }
         return null;
-    };
+    }
+
+    private static Comparator<Matcher> MATCHER_COMPARATOR = comparing((Matcher m) -> m.group(1), BIG_INT_COMPARATOR)
+            .thenComparing(comparing(m -> m.group(2), STRING_COMPARATOR))
+            .thenComparing(comparing(m -> m.group(3), BIG_INT_COMPARATOR));
+
+    private Comparator<File> fallback;
+
+    /**
+     * @param fallback
+     *            the comparator to use when numerical sorting fails. Default is file name case insensitive compare
+     */
+    public NumericalSortFilenameComparator(Comparator<File> fallback) {
+        this.fallback = ofNullable(fallback).orElse(nullsLast(comparing(File::getName, String.CASE_INSENSITIVE_ORDER)));
+    }
+
+    /**
+     * Comparator performing numerical sort with fallback to file name case insensitive compare in case numerical sort fails
+     */
+    public NumericalSortFilenameComparator() {
+        this(null);
+    }
 
     @Override
     public int compare(File a, File b) {
-        try {
-            BigInteger bigA = leadingDigits.apply(a);
-            BigInteger bigB = leadingDigits.apply(b);
-            if (nonNull(bigA) && nonNull(bigB)) {
-                return bigA.compareTo(bigB);
-            }
-        } catch (NumberFormatException | IllegalStateException e) {
-            LOG.warn("Unexpected conversion issue", e);
+        Matcher m1 = ofNullable(a).map(NumericalSortFilenameComparator::basename).map(PATTERN::matcher)
+                .filter(Matcher::matches).orElse(null);
+        Matcher m2 = ofNullable(b).map(NumericalSortFilenameComparator::basename).map(PATTERN::matcher)
+                .filter(Matcher::matches).orElse(null);
+
+        if (nonNull(m1) && nonNull(m2) && (isEmpty(m1.group(1)) ^ isEmpty(m2.group(1)))) {
+            // one start with digits the other doesn't, we can just go with the fallback
+            return fallback.compare(a, b);
         }
-        return 0;
+
+        int retVal = nullsLast(MATCHER_COMPARATOR).compare(m1, m2);
+        if (retVal == 0) {
+            // from the numerical sort of point of view they are equivalent (ex. 001banana.pdf and 1banana.pdf)
+            return fallback.compare(a, b);
+        }
+        return retVal;
     }
+
 }


=====================================
src/test/java/org/sejda/commons/util/NumericalSortFilenameComparatorTest.java
=====================================
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 Sober Lemur S.a.s. di Vacondio Andrea and Sejda BV
+ * Copyright 2018 Sober Lemur S.a.s. di Vacondio Andrea and Sejda BV
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,34 +15,64 @@
  */
 package org.sejda.commons.util;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
 
 import org.junit.jupiter.api.Test;
 
+/**
+ * @author Andrea Vacondio
+ *
+ */
 public class NumericalSortFilenameComparatorTest {
-
     @Test
     public void nulls() {
-        assertEquals(0, new NumericalSortFilenameComparator().compare(null, new File("bla")));
-        assertEquals(0, new NumericalSortFilenameComparator().compare(null, null));
-        assertEquals(0, new NumericalSortFilenameComparator().compare(new File("bla"), null));
+        NumericalSortFilenameComparator victim = new NumericalSortFilenameComparator();
+        assertTrue(victim.compare(null, new File("bla")) > 0);
+        assertTrue(victim.compare(null, null) == 0);
+        assertTrue(victim.compare(new File("bla"), null) < 0);
     }
 
     @Test
     public void nonDigit() {
-        assertEquals(0, new NumericalSortFilenameComparator().compare(new File("123.pdf"), new File("bla.pdf")));
-        assertEquals(0, new NumericalSortFilenameComparator().compare(new File("bla"), new File("123.pdf")));
+        NumericalSortFilenameComparator victim = new NumericalSortFilenameComparator();
+        assertTrue(victim.compare(new File("123.pdf"), new File("bla.pdf")) < 0);
+        assertTrue(victim.compare(new File("bla.pdf"), new File("123.pdf")) > 0);
+        assertTrue(victim.compare(new File("bla.pdf"), new File("abc.pdf")) > 0);
+        assertTrue(victim.compare(new File("bla.pdf"), new File("bla.pdf")) == 0);
+        assertTrue(victim.compare(new File("bla.pdf"), new File("bla123.pdf")) < 0);
+        assertTrue(victim.compare(new File("123bla.pdf"), new File("123.pdf")) > 0);
+    }
+
+    @Test
+    public void leadingDigits() {
+        NumericalSortFilenameComparator victim = new NumericalSortFilenameComparator();
+        assertTrue(victim.compare(new File("123.pdf"), new File("1bla.pdf")) > 0);
+        assertTrue(victim.compare(new File("123bla.pdf"), new File("1bla.pdf")) > 0);
+        assertTrue(victim.compare(new File("1.pdf"), new File("001bla.pdf")) > 0);
+        assertTrue(victim.compare(new File("1bla.pdf"), new File("001bla.pdf")) > 0);
+        assertTrue(victim.compare(new File("005bla.pdf"), new File("500.pdf")) < 0);
+    }
+
+    @Test
+    public void trailingDigits() {
+        NumericalSortFilenameComparator victim = new NumericalSortFilenameComparator();
+        assertTrue(victim.compare(new File("123.pdf"), new File("bla1.pdf")) < 0);
+        assertTrue(victim.compare(new File("bla 10.pdf"), new File("bla 1.pdf")) > 0);
+        assertTrue(victim.compare(new File("1.pdf"), new File("bla001.pdf")) < 0);
+        assertTrue(victim.compare(new File("bla1.pdf"), new File("bla001.pdf")) > 0);
+        assertTrue(victim.compare(new File("bla005.pdf"), new File("500.pdf")) > 0);
     }
 
     @Test
-    public void digits() {
-        assertEquals(1, new NumericalSortFilenameComparator().compare(new File("123.pdf"), new File("1bla.pdf")));
-        assertEquals(1, new NumericalSortFilenameComparator().compare(new File("123bla.pdf"), new File("1bla.pdf")));
-        assertEquals(0, new NumericalSortFilenameComparator().compare(new File("1.pdf"), new File("001bla.pdf")));
-        assertEquals(0, new NumericalSortFilenameComparator().compare(new File("1bla.pdf"), new File("001bla.pdf")));
-        assertEquals(-1, new NumericalSortFilenameComparator().compare(new File("005bla.pdf"), new File("500.pdf")));
-        assertEquals(-1, new NumericalSortFilenameComparator().compare(new File("005bla.pdf"), new File("500bla.pdf")));
+    public void mixed() {
+        NumericalSortFilenameComparator victim = new NumericalSortFilenameComparator();
+        assertTrue(victim.compare(new File("bla 1.pdf"), new File("vol 10.pdf")) < 0);
+        assertTrue(victim.compare(new File("20 bla 1.pdf"), new File("03 vol 10.pdf")) > 0);
+        assertTrue(victim.compare(new File("20 bla 1.pdf"), new File("20 bla 5.pdf")) < 0);
+        assertTrue(victim.compare(new File("banana.pdf"), new File("avocado.pdf")) > 0);
+        assertTrue(victim.compare(new File("chuck.pdf"), new File("chuck.abc")) > 0);
+        assertTrue(victim.compare(new File("1234file.pdf"), new File("chuck.abc")) < 0);
     }
 }



View it on GitLab: https://salsa.debian.org/java-team/libsejda-commons-java/-/commit/3d141f3c597810c067cedd2b1d37daf6f9030bdb

-- 
View it on GitLab: https://salsa.debian.org/java-team/libsejda-commons-java/-/commit/3d141f3c597810c067cedd2b1d37daf6f9030bdb
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20210130/a8b32caf/attachment.html>


More information about the pkg-java-commits mailing list