diff --git a/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java b/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java
index 6786065..394c025 100644
--- a/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java
+++ b/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java
@@ -48,5 +48,5 @@
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
import org.apache.pdfbox.pdmodel.interactive.pagenavigation.PDThreadBead;
-import org.apache.pdfbox.util.QuickSort;
+import org.apache.pdfbox.util.BubbleSort;
/**
@@ -64,5 +64,5 @@
private static float defaultIndentThreshold = 2.0f;
private static float defaultDropThreshold = 2.5f;
- private static final boolean useCustomQuickSort;
+ private static final boolean useCustomSort;
private static final Log LOG = LogFactory.getLog(PDFTextStripper.class);
@@ -111,5 +111,5 @@
}
- // check if we need to use the custom quicksort algorithm as a
+ // check if we need to use the custom sorting algorithm as a
// workaround to the transitivity issue of TextPositionComparator:
// https://issues.apache.org/jira/browse/PDFBOX-1512
@@ -125,7 +125,7 @@
{
// when run in an applet ignore and use default
- // assume 1.7 or higher so that quicksort is used
+ // assume 1.7 or higher so that the custom sort is used
}
- useCustomQuickSort = !is16orLess;
+ useCustomSort = !is16orLess;
}
@@ -509,8 +509,8 @@
// because the TextPositionComparator is not transitive, but
// JDK7+ enforces transitivity on comparators, we need to use
- // a custom quicksort implementation (which is slower, unfortunately).
- if (useCustomQuickSort)
+ // a custom stable sorting algorithm (which is slower, unfortunately).
+ if (useCustomSort)
{
- QuickSort.sort(textList, comparator);
+ BubbleSort.sort(textList, comparator);
}
else
diff --git a/pdfbox/src/main/java/org/apache/pdfbox/util/BubbleSort.java b/pdfbox/src/main/java/org/apache/pdfbox/util/BubbleSort.java
new file mode 100644
index 0000000..e964cdb
--- /dev/null
+++ b/pdfbox/src/main/java/org/apache/pdfbox/util/BubbleSort.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.pdfbox.util;
+
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Bubble sort implementation based on https://de.wikipedia.org/wiki/Bubblesort and the example bubbleSort3.
+ *
+ *
+ * Bubble sort is a stable sorting algorithm with
+ *
+ * - Worst case performance O(n2)
+ * - Best case performance O(n)
+ * - Average case performance O(n2)
+ * - Worst case space complexity O(1) auxiliary
+ *
+ *
+ * @author Lars Torunski
+ */
+public final class BubbleSort
+{
+
+ private BubbleSort()
+ {
+ }
+
+ /**
+ * Sorts the specified list according to the order induced by the specified comparator.
+ *
+ *
+ * This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
+ *
+ *
+ * The specified list must be modifiable, but need not be resizable.
+ *
+ * @param the class of the objects in the list
+ * @param list the list to be sorted.
+ * @param c the comparator to determine the order of the list.
+ */
+ public static void sort(List list, Comparator cmp)
+ {
+ int n = list.size();
+ while (n > 1)
+ {
+ int newN = 1;
+ for (int i = 0; i < n - 1; ++i)
+ {
+ if (cmp.compare(list.get(i), list.get(i + 1)) > 0)
+ {
+ swap(list, i, i + 1);
+ newN = i + 1;
+ }
+ }
+ n = newN;
+ }
+ }
+
+ private static void swap(List list, int i, int j)
+ {
+ T tmp = list.get(i);
+ list.set(i, list.get(j));
+ list.set(j, tmp);
+ }
+
+}
diff --git a/pdfbox/src/test/java/org/apache/pdfbox/util/TestBubbleSort.java b/pdfbox/src/test/java/org/apache/pdfbox/util/TestBubbleSort.java
new file mode 100644
index 0000000..dded6ae
--- /dev/null
+++ b/pdfbox/src/test/java/org/apache/pdfbox/util/TestBubbleSort.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * 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.apache.pdfbox.util;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Lars Torunski
+ */
+public class TestBubbleSort
+{
+
+ private static final Comparator extends Comparable> OBJCOMP = new Comparator()
+ {
+ @Override
+ public int compare(Comparable object1, Comparable object2)
+ {
+ return object1.compareTo(object2);
+ }
+ };
+
+ > void doTest(T[] input, T[] expected)
+ {
+ List list = Arrays.asList(input);
+ BubbleSort.sort(list, (Comparator) OBJCOMP);
+
+ assertTrue(Arrays.equals(list.toArray(new Object[input.length]), input));
+ }
+
+ /**
+ * Test for different cases.
+ */
+ @Test
+ public void testBubbleSort()
+ {
+
+ {
+ Integer[] input = new Integer[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
+ Integer[] expected = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 4, 3, 2, 1, 9, 8, 7, 6, 5 };
+ Integer[] expected = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] {};
+ Integer[] expected = new Integer[] {};
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 5 };
+ Integer[] expected = new Integer[] { 5 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 5, 6 };
+ Integer[] expected = new Integer[] { 5, 6 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 6, 5 };
+ Integer[] expected = new Integer[] { 5, 6 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 6, 5, 7 };
+ Integer[] expected = new Integer[] { 5, 6, 7 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 5, 6, 7 };
+ Integer[] expected = new Integer[] { 5, 6, 7 };
+ doTest(input, expected);
+ }
+
+ {
+ Integer[] input = new Integer[] { 7, 5, 6 };
+ Integer[] expected = new Integer[] { 5, 6, 7 };
+ doTest(input, expected);
+ }
+
+ }
+}