@@ -1207,13 +1207,13 @@ private static <T> Optional<ScoringPredicate<T>> create(final ExpressionTerm ter
1207
1207
final Function <T , String > extractionFunction ) {
1208
1208
return ifValue (term , () -> {
1209
1209
// See if this is a wildcard equals.
1210
- final String replaced = makePattern ( term .getValue ());
1211
- if (! Objects . equals ( term .getValue (), replaced )) {
1210
+ if ( containsWildcard ( term .getValue ())) {
1211
+ final String wildcardPattern = replaceWildcards ( term .getValue ());
1212
1212
return new StringRegex <>(term , extractionFunction ,
1213
- Pattern .compile (replaced , Pattern .CASE_INSENSITIVE ));
1213
+ Pattern .compile (wildcardPattern , Pattern .CASE_INSENSITIVE ));
1214
1214
}
1215
1215
1216
- return new StringEquals <T >(term , term .getValue (), extractionFunction );
1216
+ return new StringEquals <T >(term , unescape ( term .getValue () ), extractionFunction );
1217
1217
});
1218
1218
}
1219
1219
@@ -1235,13 +1235,13 @@ private static <T> Optional<ScoringPredicate<T>> create(final ExpressionTerm ter
1235
1235
final Function <T , String > extractionFunction ) {
1236
1236
return ifValue (term , () -> {
1237
1237
// See if this is a wildcard equals.
1238
- final String replaced = makePattern ( term .getValue ());
1239
- if (! Objects . equals ( term .getValue (), replaced )) {
1238
+ if ( containsWildcard ( term .getValue ())) {
1239
+ final String wildcardPattern = replaceWildcards ( term .getValue ());
1240
1240
return new StringRegex <>(term , extractionFunction ,
1241
- Pattern .compile (replaced ));
1241
+ Pattern .compile (wildcardPattern ));
1242
1242
}
1243
1243
1244
- return new StringEqualsCaseSensitive <T >(term , term .getValue (), extractionFunction );
1244
+ return new StringEqualsCaseSensitive <T >(term , unescape ( term .getValue () ), extractionFunction );
1245
1245
});
1246
1246
}
1247
1247
@@ -1257,23 +1257,24 @@ private static class StringContains<T> extends ExpressionTermPredicate<T> {
1257
1257
private final String value ;
1258
1258
1259
1259
private StringContains (final ExpressionTerm term ,
1260
+ final String value ,
1260
1261
final Function <T , String > extractionFunction ) {
1261
1262
super (term );
1262
1263
this .extractionFunction = extractionFunction ;
1263
- value = term . getValue (). toLowerCase () ;
1264
+ this . value = value ;
1264
1265
}
1265
1266
1266
1267
private static <T > Optional <ScoringPredicate <T >> create (final ExpressionTerm term ,
1267
1268
final Function <T , String > extractionFunction ) {
1268
1269
return ifValue (term , () -> {
1269
1270
// See if this is a wildcard contains.
1270
- final String replaced = makePattern ( term .getValue ());
1271
- if (! Objects . equals ( term .getValue (), replaced )) {
1271
+ if ( containsWildcard ( term .getValue ())) {
1272
+ final String wildcardPattern = replaceWildcards ( term .getValue ());
1272
1273
return new StringRegex <>(term , extractionFunction ,
1273
- Pattern .compile (".*" + replaced + ".*" , Pattern .CASE_INSENSITIVE ));
1274
+ Pattern .compile (".*" + wildcardPattern + ".*" , Pattern .CASE_INSENSITIVE ));
1274
1275
}
1275
1276
1276
- return new StringContains <>(term , extractionFunction );
1277
+ return new StringContains <>(term , unescape ( term . getValue ()). toLowerCase (), extractionFunction );
1277
1278
});
1278
1279
}
1279
1280
@@ -1290,21 +1291,22 @@ public boolean test(final T values) {
1290
1291
private static class StringContainsCaseSensitive <T > extends StringExpressionTermPredicate <T > {
1291
1292
1292
1293
private StringContainsCaseSensitive (final ExpressionTerm term ,
1294
+ final String value ,
1293
1295
final Function <T , String > extractionFunction ) {
1294
- super (term , term . getValue () , extractionFunction );
1296
+ super (term , value , extractionFunction );
1295
1297
}
1296
1298
1297
1299
private static <T > Optional <ScoringPredicate <T >> create (final ExpressionTerm term ,
1298
1300
final Function <T , String > extractionFunction ) {
1299
1301
return ifValue (term , () -> {
1300
1302
// See if this is a wildcard contains.
1301
- final String replaced = makePattern ( term .getValue ());
1302
- if (! Objects . equals ( term .getValue (), replaced )) {
1303
+ if ( containsWildcard ( term .getValue ())) {
1304
+ final String wildcardPattern = replaceWildcards ( term .getValue ());
1303
1305
return new StringRegex <>(term , extractionFunction ,
1304
- Pattern .compile (".*" + replaced + ".*" ));
1306
+ Pattern .compile (".*" + wildcardPattern + ".*" ));
1305
1307
}
1306
1308
1307
- return new StringContainsCaseSensitive <>(term , extractionFunction );
1309
+ return new StringContainsCaseSensitive <>(term , unescape ( term . getValue ()), extractionFunction );
1308
1310
});
1309
1311
}
1310
1312
@@ -1711,34 +1713,72 @@ public boolean test(final T values) {
1711
1713
}
1712
1714
}
1713
1715
1714
- public static String makePattern (final String value ) {
1715
- int index = 0 ;
1716
+ public static String replaceWildcards (final String value ) {
1717
+ boolean escaped = false ;
1718
+
1716
1719
final char [] chars = value .toCharArray ();
1717
- final char [] out = new char [ chars . length * 2 ] ;
1720
+ final StringBuilder sb = new StringBuilder () ;
1718
1721
for (int i = 0 ; i < chars .length ; i ++) {
1719
1722
final char c = chars [i ];
1720
- if (c == '\\' ) {
1721
- if (i < chars .length - 1 ) {
1722
- final char c2 = chars [i + 1 ];
1723
- if (c2 == '*' || c2 == '?' ) {
1724
- out [index ++] = c2 ;
1725
- i ++;
1726
- } else {
1727
- out [index ++] = c ;
1728
- }
1723
+ if (escaped ) {
1724
+ if (Character .isLetterOrDigit (c )) {
1725
+ sb .append (c );
1729
1726
} else {
1730
- out [index ++] = c ;
1727
+ // Might be a special char so escape it
1728
+ sb .append (Pattern .quote (String .valueOf (c )));
1731
1729
}
1730
+ escaped = false ;
1731
+ } else if (c == '\\' && chars .length > i + 1 && (chars [i + 1 ] == '*' || chars [i + 1 ] == '?' )) {
1732
+ escaped = true ;
1733
+ } else if (c == '*' ) {
1734
+ sb .append ('.' );
1735
+ sb .append (c );
1736
+ } else if (c == '?' ) {
1737
+ sb .append ('.' );
1738
+ } else if (Character .isLetterOrDigit (c )) {
1739
+ sb .append (c );
1740
+ } else {
1741
+ // Might be a special char so escape it
1742
+ sb .append (Pattern .quote (String .valueOf (c )));
1743
+ }
1744
+ }
1745
+ return sb .toString ();
1746
+ }
1747
+
1748
+ public static boolean containsWildcard (final String value ) {
1749
+ boolean escaped = false ;
1750
+ final char [] chars = value .toCharArray ();
1751
+ for (int i = 0 ; i < chars .length ; i ++) {
1752
+ final char c = chars [i ];
1753
+ if (escaped ) {
1754
+ escaped = false ;
1755
+ } else if (c == '\\' && chars .length > i + 1 && (chars [i + 1 ] == '*' || chars [i + 1 ] == '?' )) {
1756
+ escaped = true ;
1732
1757
} else if (c == '*' ) {
1733
- out [index ++] = '.' ;
1734
- out [index ++] = c ;
1758
+ return true ;
1735
1759
} else if (c == '?' ) {
1736
- out [index ++] = '.' ;
1760
+ return true ;
1761
+ }
1762
+ }
1763
+ return false ;
1764
+ }
1765
+
1766
+ public static String unescape (final String value ) {
1767
+ boolean escaped = false ;
1768
+ final char [] chars = value .toCharArray ();
1769
+ final StringBuilder sb = new StringBuilder (chars .length );
1770
+ for (int i = 0 ; i < chars .length ; i ++) {
1771
+ final char c = chars [i ];
1772
+ if (escaped ) {
1773
+ sb .append (c );
1774
+ escaped = false ;
1775
+ } else if (c == '\\' && chars .length > i + 1 && (chars [i + 1 ] == '*' || chars [i + 1 ] == '?' )) {
1776
+ escaped = true ;
1737
1777
} else {
1738
- out [ index ++] = c ;
1778
+ sb . append ( c ) ;
1739
1779
}
1740
1780
}
1741
- return new String ( out , 0 , index );
1781
+ return sb . toString ( );
1742
1782
}
1743
1783
1744
1784
private static String [] loadDictionary (final WordListProvider wordListProvider ,
0 commit comments