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