OsmAnd/OsmAnd-java/src/net/osmand/CollatorStringMatcher.java
2016-06-21 01:24:31 +02:00

147 lines
3.8 KiB
Java

package net.osmand;
import java.util.Locale;
/**
* 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,
CHECK_EQUALS_FROM_SPACE,
CHECK_CONTAINS
}
public CollatorStringMatcher(String part, StringMatcherMode mode) {
this.collator = OsmAndCollator.primaryCollator();
this.part = part.toLowerCase(Locale.getDefault());
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);
case CHECK_EQUALS_FROM_SPACE:
return cstartsWith(collator, base, part, true, true, true);
case CHECK_STARTS_FROM_SPACE:
return cstartsWith(collator, base, part, true, true, false);
case CHECK_STARTS_FROM_SPACE_NOT_BEGINNING:
return cstartsWith(collator, base, part, false, true, false);
case CHECK_ONLY_STARTS_WITH:
return cstartsWith(collator, base, part, true, false, false);
}
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
*/
public static boolean cstartsWith(Collator collator, String searchInParam, String theStart,
boolean checkBeginning, boolean checkSpaces, boolean equals) {
String searchIn = searchInParam.toLowerCase(Locale.getDefault());
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) {
if (equals) {
if (startLength == searchInLength || isSpace(searchIn.charAt(startLength))) {
return true;
}
} else {
return true;
}
}
}
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)) {
if(equals) {
if(i + startLength == searchInLength || isSpace(searchIn.charAt(i + startLength))) {
return true;
}
} else {
return true;
}
}
}
}
}
return false;
}
private static boolean isSpace(char c){
return !Character.isLetter(c) && !Character.isDigit(c);
}
}