001
014
015 package com.liferay.portal.kernel.util;
016
017 import java.io.Serializable;
018
019 import java.util.Comparator;
020
021
024 public class NaturalOrderStringComparator
025 implements Comparator<String>, Serializable {
026
027 public NaturalOrderStringComparator() {
028 this(true, false);
029 }
030
031 public NaturalOrderStringComparator(
032 boolean ascending, boolean caseSensitive) {
033
034 _ascending = ascending;
035 _caseSensitive = caseSensitive;
036 }
037
038 @Override
039 public int compare(String s1, String s2) {
040 if (s1 == null) {
041 s1 = StringPool.BLANK;
042 }
043
044 if (s2 == null) {
045 s2 = StringPool.BLANK;
046 }
047
048 int value = 0;
049
050 int i1 = 0;
051 int i2 = 0;
052
053 int length1 = s1.length();
054 int length2 = s2.length();
055
056 while ((i1 < length1) && (i2 < length2)) {
057 char c1 = s1.charAt(i1);
058 char c2 = s2.charAt(i2);
059
060 if (Validator.isDigit(c1) && Validator.isDigit(c2)) {
061 String leadingDigitsAsString1 = StringUtil.extractLeadingDigits(
062 s1.substring(i1));
063 String leadingDigitsAsString2 = StringUtil.extractLeadingDigits(
064 s2.substring(i2));
065
066 int leadingNumber1 = GetterUtil.getInteger(
067 leadingDigitsAsString1);
068 int leadingNumber2 = GetterUtil.getInteger(
069 leadingDigitsAsString2);
070
071 if (leadingNumber1 != leadingNumber2) {
072 value = leadingNumber1 - leadingNumber2;
073
074 break;
075 }
076
077 i1 += leadingDigitsAsString1.length();
078 i2 += leadingDigitsAsString2.length();
079
080 continue;
081 }
082
083 if (isCheckSpecialCharacters() && Validator.isAscii(c1) &&
084 Validator.isAscii(c2)) {
085
086 boolean isDigitOrLetter1 = _isDigitOrLetter(c1);
087 boolean isDigitOrLetter2 = _isDigitOrLetter(c2);
088
089 if (isDigitOrLetter1 ^ isDigitOrLetter2) {
090 if (isDigitOrLetter1) {
091 value = 1;
092 }
093 else {
094 value = -1;
095 }
096
097 break;
098 }
099 }
100
101 if (c1 == c2) {
102 i1++;
103 i2++;
104
105 continue;
106 }
107
108 if (_caseSensitive) {
109 value = c1 - c2;
110
111 break;
112 }
113 else {
114 char c1UpperCase = Character.toUpperCase(c1);
115 char c2UpperCase = Character.toUpperCase(c2);
116
117 if (c1UpperCase == c2UpperCase) {
118 i1++;
119 i2++;
120
121 continue;
122 }
123
124 value = c1UpperCase - c2UpperCase;
125
126 break;
127 }
128 }
129
130 if ((value == 0) && (length1 != length2)) {
131 if ((length1 == i1) && (length2 == i2)) {
132 value = length2 - length1;
133 }
134 else {
135 value = length1 - length2;
136 }
137 }
138
139 if (_ascending) {
140 return value;
141 }
142 else {
143 return -value;
144 }
145 }
146
147 protected boolean isCheckSpecialCharacters() {
148 return true;
149 }
150
151 private boolean _isDigitOrLetter(char c) {
152 if (Validator.isChar(c) || Validator.isDigit(c)) {
153 return true;
154 }
155 else {
156 return false;
157 }
158 }
159
160 private final boolean _ascending;
161 private final boolean _caseSensitive;
162
163 }