refactor: подтянуть Legal NER, переформатировать код и добавить тесты
Слияние с 685ec97 (третья ступень NER для юридических реквизитов),
код приведён к google-java-format, добавлены юнит-тесты
AdaptiveConcurrencyLimiter/SystemsConfig/PayloadCipher.
This commit is contained in:
@@ -4,51 +4,47 @@ import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Словарь населённых пунктов России — проверка того, что значение, пойманное
|
||||
* правилом {@code ADDRESS_CITY}, действительно похоже на существующий город,
|
||||
* село, посёлок или другой населённый пункт, а не на произвольное слово с
|
||||
* заглавной буквы после якоря.
|
||||
* Словарь населённых пунктов России — проверка того, что значение, пойманное правилом {@code
|
||||
* ADDRESS_CITY}, действительно похоже на существующий город, село, посёлок или другой населённый
|
||||
* пункт, а не на произвольное слово с заглавной буквы после якоря.
|
||||
*
|
||||
* <p>Не только официальные города (~1100 по классификатору): перепись
|
||||
* добавляет сёла, деревни, хутора, станицы — «рп. Ильинское», «с. Кукуево»
|
||||
* из ТЗ находятся ровно за счёт неё. Какой конкретно тип населённого пункта
|
||||
* стоит перед названием, определяет якорь самого правила в {@link RuleRegistry},
|
||||
* а не этот словарь — он только подтверждает, что название реальное.
|
||||
* <p>Не только официальные города (~1100 по классификатору): перепись добавляет сёла, деревни,
|
||||
* хутора, станицы — «рп. Ильинское», «с. Кукуево» из ТЗ находятся ровно за счёт неё. Какой
|
||||
* конкретно тип населённого пункта стоит перед названием, определяет якорь самого правила в {@link
|
||||
* RuleRegistry}, а не этот словарь — он только подтверждает, что название реальное.
|
||||
*
|
||||
* <p>Сравнение по началу слова, а не точным совпадением: падежные окончания
|
||||
* («в Москве», «из Казани») тем самым покрываются без отдельного разбора
|
||||
* морфологии, как и у известных людей в {@link NameDictionary}.
|
||||
* <p>Сравнение по началу слова, а не точным совпадением: падежные окончания («в Москве», «из
|
||||
* Казани») тем самым покрываются без отдельного разбора морфологии, как и у известных людей в
|
||||
* {@link NameDictionary}.
|
||||
*/
|
||||
public final class ToponymDictionary {
|
||||
|
||||
private static final Set<String> SETTLEMENT_STEMS = ResourceLoader.set("/names/settlements.txt").stream()
|
||||
.map(Declension::withoutInflectedEnding)
|
||||
.collect(java.util.stream.Collectors.toUnmodifiableSet());
|
||||
private static final Set<String> SETTLEMENT_STEMS =
|
||||
ResourceLoader.set("/names/settlements.txt").stream()
|
||||
.map(Declension::withoutInflectedEnding)
|
||||
.collect(java.util.stream.Collectors.toUnmodifiableSet());
|
||||
|
||||
private ToponymDictionary() {
|
||||
}
|
||||
private ToponymDictionary() {}
|
||||
|
||||
/**
|
||||
* Похоже ли значение на название населённого пункта из словаря в любом
|
||||
* падеже.
|
||||
*
|
||||
* <p>Названия на согласную склоняются добавлением окончания («Тамбов» →
|
||||
* «Тамбове»), поэтому начало слова из словаря — уже достаточный признак.
|
||||
* Названия на гласную меняют последнюю букву («Москва» → «Москве»), для
|
||||
* них сравнение идёт по основе без неё — так же, как с личными именами
|
||||
* в {@link NameDictionary}.
|
||||
*
|
||||
* <p>Проверяются префиксы значения по множеству, а не каждая из ~80 000
|
||||
* основ по значению: перебор списка на каждое совпадение правила был бы
|
||||
* на порядки дороже, чем нужно — префиксов у слова не больше, чем в нём букв.
|
||||
*/
|
||||
public static boolean isKnownSettlement(String value) {
|
||||
String lower = value.strip().toLowerCase(Locale.ROOT);
|
||||
for (int length = lower.length(); length > 0; length--) {
|
||||
if (SETTLEMENT_STEMS.contains(lower.substring(0, length))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
/**
|
||||
* Похоже ли значение на название населённого пункта из словаря в любом падеже.
|
||||
*
|
||||
* <p>Названия на согласную склоняются добавлением окончания («Тамбов» → «Тамбове»), поэтому
|
||||
* начало слова из словаря — уже достаточный признак. Названия на гласную меняют последнюю букву
|
||||
* («Москва» → «Москве»), для них сравнение идёт по основе без неё — так же, как с личными именами
|
||||
* в {@link NameDictionary}.
|
||||
*
|
||||
* <p>Проверяются префиксы значения по множеству, а не каждая из ~80 000 основ по значению:
|
||||
* перебор списка на каждое совпадение правила был бы на порядки дороже, чем нужно — префиксов у
|
||||
* слова не больше, чем в нём букв.
|
||||
*/
|
||||
public static boolean isKnownSettlement(String value) {
|
||||
String lower = value.strip().toLowerCase(Locale.ROOT);
|
||||
for (int length = lower.length(); length > 0; length--) {
|
||||
if (SETTLEMENT_STEMS.contains(lower.substring(0, length))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user