]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.server/src/org/simantics/document/server/client/AlphanumericComparator.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / client / AlphanumericComparator.java
1 package org.simantics.document.server.client;
2
3 import java.util.Comparator;
4
5 /**
6  * This is an updated version with enhancements made by Daniel Migowski,
7  * Andre Bogus, and David Koelle
8  *
9  * To convert to use Templates (Java 1.5+):
10  *   - Change "implements Comparator" to "implements Comparator<String>"
11  *   - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
12  *   - Remove the type checking and casting in compare().
13  *
14  * To use this class:
15  *   Use the static "sort" method from the java.util.Collections class:
16  *   Collections.sort(your list, new AlphanumComparator());
17  */
18 public class AlphanumericComparator implements Comparator<String>
19 {
20     private final boolean isDigit(char ch)
21     {
22         return ch >= 48 && ch <= 57;
23     }
24
25     /** Length of string is passed in for improved efficiency (only need to calculate it once) **/
26     private final String getChunk(String s, int slength, int marker)
27     {
28         StringBuilder chunk = new StringBuilder();
29         char c = s.charAt(marker);
30         chunk.append(c);
31         marker++;
32         if (isDigit(c))
33         {
34             while (marker < slength)
35             {
36                 c = s.charAt(marker);
37                 if (!isDigit(c))
38                     break;
39                 chunk.append(c);
40                 marker++;
41             }
42         } else
43         {
44             while (marker < slength)
45             {
46                 c = s.charAt(marker);
47                 if (isDigit(c))
48                     break;
49                 chunk.append(c);
50                 marker++;
51             }
52         }
53         return chunk.toString();
54     }
55
56     public int compare(String o1, String o2)
57     {
58         if (!(o1 instanceof String) || !(o2 instanceof String))
59         {
60             return 0;
61         }
62         String s1 = (String)o1;
63         String s2 = (String)o2;
64
65         int thisMarker = 0;
66         int thatMarker = 0;
67         int s1Length = s1.length();
68         int s2Length = s2.length();
69
70         while (thisMarker < s1Length && thatMarker < s2Length)
71         {
72             String thisChunk = getChunk(s1, s1Length, thisMarker);
73             thisMarker += thisChunk.length();
74
75             String thatChunk = getChunk(s2, s2Length, thatMarker);
76             thatMarker += thatChunk.length();
77
78             // If both chunks contain numeric characters, sort them numerically
79             int result = 0;
80             if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
81             {
82                 // Simple chunk comparison by length.
83                 int thisChunkLength = thisChunk.length();
84                 result = thisChunkLength - thatChunk.length();
85                 // If equal, the first different number counts
86                 if (result == 0)
87                 {
88                     for (int i = 0; i < thisChunkLength; i++)
89                     {
90                         result = thisChunk.charAt(i) - thatChunk.charAt(i);
91                         if (result != 0)
92                         {
93                             return result;
94                         }
95                     }
96                 }
97             } else
98             {
99                 result = thisChunk.compareTo(thatChunk);
100             }
101
102             if (result != 0)
103                 return result;
104         }
105
106         return s1Length - s2Length;
107     }
108
109 }
110