2013-04-18 23:35:02 +02:00
|
|
|
package net.osmand;
|
|
|
|
|
2015-06-15 21:32:35 +02:00
|
|
|
import java.util.Locale;
|
|
|
|
|
2013-04-18 23:35:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract collator matcher that basically supports subclasses with some collator
|
|
|
|
* matching.
|
|
|
|
*
|
|
|
|
* @author pavol.zibrita
|
|
|
|
*/
|
|
|
|
public class CollatorStringMatcher implements StringMatcher {
|
|
|
|
|
|
|
|
private final Collator collator;
|
|
|
|
private final StringMatcherMode mode;
|
|
|
|
private final String part;
|
|
|
|
|
|
|
|
public static enum StringMatcherMode {
|
|
|
|
CHECK_ONLY_STARTS_WITH,
|
|
|
|
CHECK_STARTS_FROM_SPACE,
|
|
|
|
CHECK_STARTS_FROM_SPACE_NOT_BEGINNING,
|
2016-06-21 01:24:25 +02:00
|
|
|
CHECK_EQUALS_FROM_SPACE,
|
2013-04-18 23:35:02 +02:00
|
|
|
CHECK_CONTAINS
|
|
|
|
}
|
|
|
|
|
|
|
|
public CollatorStringMatcher(String part, StringMatcherMode mode) {
|
2014-04-12 23:37:18 +02:00
|
|
|
this.collator = OsmAndCollator.primaryCollator();
|
2015-06-15 21:32:35 +02:00
|
|
|
this.part = part.toLowerCase(Locale.getDefault());
|
2013-04-18 23:35:02 +02:00
|
|
|
this.mode = mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Collator getCollator() {
|
|
|
|
return collator;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean matches(String name) {
|
|
|
|
return cmatches(collator, name, part, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean cmatches(Collator collator, String base, String part, StringMatcherMode mode){
|
|
|
|
switch (mode) {
|
|
|
|
case CHECK_CONTAINS:
|
|
|
|
return ccontains(collator, base, part);
|
2016-06-21 01:24:25 +02:00
|
|
|
case CHECK_EQUALS_FROM_SPACE:
|
|
|
|
return cstartsWith(collator, base, part, true, true, true);
|
2013-04-18 23:35:02 +02:00
|
|
|
case CHECK_STARTS_FROM_SPACE:
|
2016-06-21 01:24:25 +02:00
|
|
|
return cstartsWith(collator, base, part, true, true, false);
|
2013-04-18 23:35:02 +02:00
|
|
|
case CHECK_STARTS_FROM_SPACE_NOT_BEGINNING:
|
2016-06-21 01:24:25 +02:00
|
|
|
return cstartsWith(collator, base, part, false, true, false);
|
2013-04-18 23:35:02 +02:00
|
|
|
case CHECK_ONLY_STARTS_WITH:
|
2016-06-21 01:24:25 +02:00
|
|
|
return cstartsWith(collator, base, part, true, false, false);
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if part contains in base
|
|
|
|
*
|
|
|
|
* @param collator Collator to use
|
|
|
|
* @param part String to search
|
|
|
|
* @param base String where to search
|
|
|
|
* @return true if part is contained in base
|
|
|
|
*/
|
|
|
|
public static boolean ccontains(Collator collator, String base, String part) {
|
|
|
|
int pos = 0;
|
|
|
|
if (part.length() > 3) {
|
|
|
|
// improve searching by searching first 3 characters
|
|
|
|
pos = cindexOf(collator, pos, part.substring(0, 3), base);
|
|
|
|
if (pos == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = cindexOf(collator, pos, part, base);
|
|
|
|
if (pos == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static int cindexOf(Collator collator, int start, String part, String base) {
|
|
|
|
for (int pos = start; pos <= base.length() - part.length(); pos++) {
|
|
|
|
if (collator.equals(base.substring(pos, pos + part.length()), part)) {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if string starts with another string.
|
|
|
|
* Special check try to find as well in the middle of name
|
|
|
|
*
|
|
|
|
* @param collator
|
|
|
|
* @param searchIn
|
|
|
|
* @param theStart
|
|
|
|
* @return true if searchIn starts with token
|
|
|
|
*/
|
2015-06-15 21:32:35 +02:00
|
|
|
public static boolean cstartsWith(Collator collator, String searchInParam, String theStart,
|
2016-06-21 01:24:25 +02:00
|
|
|
boolean checkBeginning, boolean checkSpaces, boolean equals) {
|
2015-06-15 21:32:35 +02:00
|
|
|
String searchIn = searchInParam.toLowerCase(Locale.getDefault());
|
2013-04-18 23:35:02 +02:00
|
|
|
int startLength = theStart.length();
|
|
|
|
int searchInLength = searchIn.length();
|
|
|
|
if (startLength == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (startLength > searchInLength) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// simulate starts with for collator
|
|
|
|
if (checkBeginning) {
|
|
|
|
boolean starts = collator.equals(searchIn.substring(0, startLength), theStart);
|
|
|
|
if (starts) {
|
2016-06-21 01:24:25 +02:00
|
|
|
if (equals) {
|
|
|
|
if (startLength == searchInLength || isSpace(searchIn.charAt(startLength))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (checkSpaces) {
|
|
|
|
for (int i = 1; i <= searchInLength - startLength; i++) {
|
|
|
|
if (isSpace(searchIn.charAt(i - 1)) && !isSpace(searchIn.charAt(i))) {
|
|
|
|
if (collator.equals(searchIn.substring(i, i + startLength), theStart)) {
|
2016-06-21 01:24:25 +02:00
|
|
|
if(equals) {
|
|
|
|
if(i + startLength == searchInLength || isSpace(searchIn.charAt(i + startLength))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isSpace(char c){
|
|
|
|
return !Character.isLetter(c) && !Character.isDigit(c);
|
|
|
|
}
|
|
|
|
}
|